diff --git a/Documentation/ABI/testing/sysfs-bus-iio-mpu6050 b/Documentation/ABI/testing/sysfs-bus-iio-mpu6050
new file mode 100644
index 0000000..cb53737
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-mpu6050
@@ -0,0 +1,13 @@
+What:           /sys/bus/iio/devices/iio:deviceX/in_gyro_matrix
+What:           /sys/bus/iio/devices/iio:deviceX/in_accel_matrix
+What:           /sys/bus/iio/devices/iio:deviceX/in_magn_matrix
+KernelVersion:  3.4.0
+Contact:        linux-iio@vger.kernel.org
+Description:
+		This is mounting matrix for motion sensors. Mounting matrix
+		is a 3x3 unitary matrix. A typical mounting matrix would look like
+		[0, 1, 0; 1, 0, 0; 0, 0, -1]. Using this information, it would be
+		easy to tell the relative positions among sensors as well as their
+		positions relative to the board that holds these sensors. Identity matrix
+		[1, 0, 0; 0, 1, 0; 0, 0, 1] means sensor chip and device are perfectly
+		aligned with each other. All axes are exactly the same.
diff --git a/Documentation/ABI/testing/sysfs-class-pwm b/Documentation/ABI/testing/sysfs-class-pwm
new file mode 100644
index 0000000..e9be1a3
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-pwm
@@ -0,0 +1,37 @@
+What:		/sys/class/pwm/
+Date:		March 2013
+KernelVersion:	3.11
+Contact:	Lars Poeschel <poeschel@lemonage.de>
+Description:
+
+  The sysfs interface for PWM is selectable as a Kconfig option.
+  If a driver successfully probed a pwm chip, it appears at
+  /sys/class/pwm/pwmchipN/ where N is the number of it's first PWM channel. A
+  single driver may probe multiple chips. PWMs are identified as they are
+  inside the kernel, using integers in the range 0..MAX_PWMS. To use an
+  individual PWM, you have to explicitly export it by writing it's kernel
+  global number into the /sys/class/pwm/export file. Write it's number to
+  /sys/class/pwm/unexport to make the pwm available for other uses.
+  After a PWM channel is exported, it is available under
+  /sys/class/pwm/pwmN/. Under this directory you can set the parameters for
+  this PWM channel and at least let it start running.
+  See below for the parameters.
+  It is recommended to set the period_ns at first and the duty_ns after that.
+
+  See Documentation/pwm.txt for more information.
+
+Directory structure:
+
+	/sys/class/pwm
+		/export ... asks the kernel to export a PWM to userspace
+		/unexport ... to return a PWM to the kernel
+		/pwmN ... for each exported PWM #N
+			/duty_ns ... r/w, length of duty portion
+			/period_ns ... r/w, length of the pwm period
+			/polarity ... r/w, normal(0) or inverse(1) polarity
+					only created if driver supports it
+			/run ... r/w, write 1 to start and 0 to stop the pwm
+		/pwmchipN ... for each pwmchip; #N is its first PWM
+			/base ... (r/o) same as N
+			/ngpio ... (r/o) number of PWM; numbered N .. MAX_PWMS
+
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 08f01e7..38f5c7a 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -2810,6 +2810,10 @@ Your cooperation is appreciated.
 		 211 = /dev/ttyMAX2		MAX3100 serial port 2
 		 212 = /dev/ttyMAX3		MAX3100 serial port 3
 
+		 220 = /dev/ttyJHD0		JHD629 pseudo serial port 0
+		 221 = /dev/ttyJHD1		JHD629 pseudo serial port 1
+		   ..
+
 205 char	Low-density serial ports (alternate device)
 		  0 = /dev/culu0		Callout device for ttyLU0
 		  1 = /dev/culu1		Callout device for ttyLU1
diff --git a/Documentation/devicetree/00-INDEX b/Documentation/devicetree/00-INDEX
index b78f691..fb932e2 100644
--- a/Documentation/devicetree/00-INDEX
+++ b/Documentation/devicetree/00-INDEX
@@ -8,3 +8,4 @@ https://lists.ozlabs.org/listinfo/devicetree-discuss
 	- this file
 booting-without-of.txt
 	- Booting Linux without Open Firmware, describes history and format of device trees.
+dt-object-internals.txt
diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
index d0051a7..3133a4b 100644
--- a/Documentation/devicetree/bindings/arm/omap/omap.txt
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -21,6 +21,8 @@ Required properties:
 Optional properties:
 - ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
   during suspend.
+- ti,deassert-hard-reset: list of hwmod and hardware reset line name pairs
+  (ascii strings) to be deasserted upon device instantiation.
 
 
 Example:
diff --git a/Documentation/devicetree/bindings/bus/ti-gpmc.txt b/Documentation/devicetree/bindings/bus/ti-gpmc.txt
new file mode 100644
index 0000000..4b87ea1
--- /dev/null
+++ b/Documentation/devicetree/bindings/bus/ti-gpmc.txt
@@ -0,0 +1,131 @@
+Device tree bindings for OMAP general purpose memory controllers (GPMC)
+
+The actual devices are instantiated from the child nodes of a GPMC node.
+
+Required properties:
+
+ - compatible:		Should be set to one of the following:
+
+			ti,omap2420-gpmc (omap2420)
+			ti,omap2430-gpmc (omap2430)
+			ti,omap3430-gpmc (omap3430 & omap3630)
+			ti,omap4430-gpmc (omap4430 & omap4460 & omap543x)
+			ti,am3352-gpmc   (am335x devices)
+
+ - reg:			A resource specifier for the register space
+			(see the example below)
+ - ti,hwmods:		Should be set to "ti,gpmc" until the DT transition is
+			completed.
+ - #address-cells:	Must be set to 2 to allow memory address translation
+ - #size-cells:		Must be set to 1 to allow CS address passing
+ - gpmc,num-cs:		The maximum number of chip-select lines that controller
+			can support.
+ - gpmc,num-waitpins:	The maximum number of wait pins that controller can
+			support.
+ - ranges:		Must be set up to reflect the memory layout with four
+			integer values for each chip-select line in use:
+
+			   <cs-number> 0 <physical address of mapping> <size>
+
+			Currently, calculated values derived from the contents
+			of the per-CS register GPMC_CONFIG7 (as set up by the
+			bootloader) are used for the physical address decoding.
+			As this will change in the future, filling correct
+			values here is a requirement.
+
+Timing properties for child nodes. All are optional and default to 0.
+
+ - gpmc,sync-clk-ps:	Minimum clock period for synchronous mode, in picoseconds
+
+ Chip-select signal timings (in nanoseconds) corresponding to GPMC_CONFIG2:
+ - gpmc,cs-on-ns:	Assertion time
+ - gpmc,cs-rd-off-ns:	Read deassertion time
+ - gpmc,cs-wr-off-ns:	Write deassertion time
+
+ ADV signal timings (in nanoseconds) corresponding to GPMC_CONFIG3:
+ - gpmc,adv-on-ns:	Assertion time
+ - gpmc,adv-rd-off-ns:	Read deassertion time
+ - gpmc,adv-wr-off-ns:	Write deassertion time
+
+ WE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
+ - gpmc,we-on-ns	Assertion time
+ - gpmc,we-off-ns:	Deassertion time
+
+ OE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
+ - gpmc,oe-on-ns:	Assertion time
+ - gpmc,oe-off-ns:	Deassertion time
+
+ Access time and cycle time timings (in nanoseconds) corresponding to
+ GPMC_CONFIG5:
+ - gpmc,page-burst-access-ns: 	Multiple access word delay
+ - gpmc,access-ns:		Start-cycle to first data valid delay
+ - gpmc,rd-cycle-ns:		Total read cycle time
+ - gpmc,wr-cycle-ns:		Total write cycle time
+ - gpmc,bus-turnaround-ns:	Turn-around time between successive accesses
+ - gpmc,cycle2cycle-delay-ns:	Delay between chip-select pulses
+ - gpmc,clk-activation-ns: 	GPMC clock activation time
+ - gpmc,wait-monitoring-ns:	Start of wait monitoring with regard to valid
+				data
+
+Boolean timing parameters. If property is present parameter enabled and
+disabled if omitted:
+ - gpmc,adv-extra-delay:	ADV signal is delayed by half GPMC clock
+ - gpmc,cs-extra-delay:		CS signal is delayed by half GPMC clock
+ - gpmc,cycle2cycle-diffcsen:	Add "cycle2cycle-delay" between successive
+				accesses to a different CS
+ - gpmc,cycle2cycle-samecsen:	Add "cycle2cycle-delay" between successive
+				accesses to the same CS
+ - gpmc,oe-extra-delay:		OE signal is delayed by half GPMC clock
+ - gpmc,we-extra-delay:		WE signal is delayed by half GPMC clock
+ - gpmc,time-para-granularity:	Multiply all access times by 2
+
+The following are only applicable to OMAP3+ and AM335x:
+ - gpmc,wr-access-ns:		In synchronous write mode, for single or
+				burst accesses, defines the number of
+				GPMC_FCLK cycles from start access time
+				to the GPMC_CLK rising edge used by the
+				memory device for the first data capture.
+ - gpmc,wr-data-mux-bus-ns:	In address-data multiplex mode, specifies
+				the time when the first data is driven on
+				the address-data bus.
+
+GPMC chip-select settings properties for child nodes. All are optional.
+
+- gpmc,burst-length	Page/burst length. Must be 4, 8 or 16.
+- gpmc,burst-wrap	Enables wrap bursting
+- gpmc,burst-read	Enables read page/burst mode
+- gpmc,burst-write	Enables write page/burst mode
+- gpmc,device-nand	Device is NAND
+- gpmc,device-width	Total width of device(s) connected to a GPMC
+			chip-select in bytes. The GPMC supports 8-bit
+			and 16-bit devices and so this property must be
+			1 or 2.
+- gpmc,mux-add-data	Address and data multiplexing configuration.
+			Valid values are 1 for address-address-data
+			multiplexing mode and 2 for address-data
+			multiplexing mode.
+- gpmc,sync-read	Enables synchronous read. Defaults to asynchronous
+			is this is not set.
+- gpmc,sync-write	Enables synchronous writes. Defaults to asynchronous
+			is this is not set.
+- gpmc,wait-pin		Wait-pin used by client. Must be less than
+			"gpmc,num-waitpins".
+- gpmc,wait-on-read	Enables wait monitoring on reads.
+- gpmc,wait-on-write	Enables wait monitoring on writes.
+
+Example for an AM33xx board:
+
+	gpmc: gpmc@50000000 {
+		compatible = "ti,am3352-gpmc";
+		ti,hwmods = "gpmc";
+		reg = <0x50000000 0x2000>;
+		interrupts = <100>;
+
+		gpmc,num-cs = <8>;
+		gpmc,num-waitpins = <2>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */
+
+		/* child nodes go here */
+	};
diff --git a/Documentation/devicetree/bindings/crypto/omap-aes.txt b/Documentation/devicetree/bindings/crypto/omap-aes.txt
new file mode 100644
index 0000000..6b21256
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/omap-aes.txt
@@ -0,0 +1,37 @@
+OMAP SoC AES crypto Module
+
+Required properties:
+
+- compatible : Should contain entries for this and backward compatible
+  AES versions:
+  - "ti,omap2-aes" for OMAP2.
+  - "ti,omap3-aes" for OMAP3.
+  - "ti,omap4-aes" for OMAP4 and AM33XX.
+  Note that the OMAP2 and 3 versions are compatible (OMAP3 supports
+  more algorithms) but they are incompatible with OMAP4.
+- ti,hwmods: Name of the hwmod associated with the AES odule
+- reg : Offset and length of the register set for the module
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this module.
+- interrupts : the interrupt number for the AES odule.
+
+Optional properties:
+- dmas: DMA controller phandle and DMA request ordered pairs.
+- dma-names: DMA request names. This string corresponds 1:1 with
+	the ordered pairs in dmas. The string naming is to be
+	"tx" for TX request and "rx" for RX request.
+
+Example:
+	/* AM335x */
+	aes: aes@53500000 {
+		compatible = "ti,omap4-aes";
+		ti,hwmods = "aes";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x53500000 0xa0>;
+		interrupt-parent = <&intc>;
+		interrupts = <102>;
+		dmas = <&edma 6
+			&edma 5>;
+		dma-names = "tx", "rx";
+	};
diff --git a/Documentation/devicetree/bindings/crypto/omap-sham.txt b/Documentation/devicetree/bindings/crypto/omap-sham.txt
new file mode 100644
index 0000000..53839cc
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/omap-sham.txt
@@ -0,0 +1,35 @@
+OMAP SoC SHA crypto Module
+
+Required properties:
+
+- compatible : Should contain entries for this and backward compatible
+  SHAM versions:
+  - "ti,omap2-sham" for OMAP2 & OMAP3.
+  - "ti,omap4-sham" for OMAP4 and AM33XX.
+  Note that these two versions are incompatible.
+- ti,hwmods: Name of the hwmod associated with the SHAM module
+- reg : Offset and length of the register set for the module
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this module.
+- interrupts : the interrupt number for the SHAM module.
+
+Optional properties:
+- dmas: DMA controller phandle and DMA request ordered pair.
+	Only one rx pair is valid per SHAM module.
+- dma-names: DMA request name. This string corresponds 1:1 with
+	the ordered pair in dmas. The string naming is to be
+	"rx" for RX request.
+
+Example:
+	/* AM335x */
+	sham: sham@53100000 {
+		compatible = "ti,omap4-sham";
+		ti,hwmods = "sham";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x53100000 0x200>;
+		interrupt-parent = <&intc>;
+		interrupts = <109>;
+		dmas = <&edma 36>;
+		dma-names = "rx";
+	};
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/ti-edma.txt b/Documentation/devicetree/bindings/dma/ti-edma.txt
new file mode 100644
index 0000000..075a60e3
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/ti-edma.txt
@@ -0,0 +1,49 @@
+TI EDMA
+
+Required properties:
+- compatible : "ti,edma3"
+- ti,hwmods: Name of the hwmods associated to the EDMA
+- ti,edma-regions: Number of regions
+- ti,edma-slots: Number of slots
+- ti,edma-queue-tc-map: List of transfer control to queue mappings
+- ti,edma-queue-priority-map: List of queue priority mappings
+- ti,edma-default-queue: Default queue value
+
+Optional properties:
+- ti,edma-reserved-channels: List of reserved channel regions
+- ti,edma-reserved-slots: List of reserved slot regions
+- ti,edma-xbar-event-map: Crossbar event to channel map
+
+Example:
+
+edma: edma@49000000 {
+	reg = <0x49000000 0x10000>;
+	interrupt-parent = <&intc>;
+	interrupts = <12 13 14>;
+	compatible = "ti,edma3";
+	ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
+	#dma-cells = <1>;
+	dma-channels = <64>;
+	ti,edma-regions = <4>;
+	ti,edma-slots = <256>;
+	ti,edma-reserved-channels = <0  2
+				     14 2
+				     26 6
+				     48 4
+				     56 8>;
+	ti,edma-reserved-slots = <0  2
+				  14 2
+				  26 6
+				  48 4
+				  56 8
+				  64 127>;
+	ti,edma-queue-tc-map = <0 0
+				1 1
+				2 2>;
+	ti,edma-queue-priority-map = <0 0
+				      1 1
+				      2 2>;
+	ti,edma-default-queue = <0>;
+	ti,edma-xbar-event-map = <1 12
+				  2 13>;
+};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
new file mode 100644
index 0000000..6a69af6
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt
@@ -0,0 +1,44 @@
+* TI - TSC ADC (Touschscreen and analog digital converter)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Required properties:
+- child "tsc"
+	ti,wires: Wires refer to application modes i.e. 4/5/8 wire touchscreen
+		  support on the platform.
+	ti,x-plate-resistance: X plate resistance
+	ti,coordinate-readouts: The sequencer supports a total of 16
+				programmable steps each step is used to
+				read a single coordinate. A single
+                                readout is enough but multiple reads can
+				increase the quality.
+				A value of 5 means, 5 reads for X, 5 for
+				Y and 2 for Z (always). This utilises 12
+				of the 16 software steps available. The
+				remaining 4 can be used by the ADC.
+	ti,wire-config: Different boards could have a different order for
+			connecting wires on touchscreen. We need to provide an
+			8 bit number where in the 1st four bits represent the
+			analog lines and the next 4 bits represent positive/
+			negative terminal on that input line. Notations to
+			represent the input lines and terminals resoectively
+			is as follows:
+			AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
+			XP  = 0, XN = 1, YP = 2, YN = 3.
+- child "adc"
+	ti,adc-channels: List of analog inputs available for ADC.
+			 AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
+
+Example:
+	tscadc: tscadc@44e0d000 {
+		compatible = "ti,ti-tscadc";
+		tsc {
+			ti,wires = <4>;
+			ti,x-plate-resistance = <200>;
+			ti,coordinate-readouts = <5>;
+			ti,wire-config = <0x00 0x11 0x22 0x33>;
+		};
+
+		adc {
+			ti,adc-channels = <4 5 6 7>;
+		};
+	}
diff --git a/Documentation/devicetree/bindings/misc/capes-beaglebone.txt b/Documentation/devicetree/bindings/misc/capes-beaglebone.txt
new file mode 100644
index 0000000..1af627a
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/capes-beaglebone.txt
@@ -0,0 +1,113 @@
+* TI Beaglebone DT Overlay Cape Driver
+
+Required properties:
+
+- compatible: "ti,bone-capemgr"
+
+- eeprom: Contains the phandle beaglebone's baseboard i2c eeprom.
+
+- baseboardmaps - node containing a list of supported
+	beaglebone revisions; each node in should have the
+	following properties:
+	- board-name: The board name stored in the baseboard
+		eeprom.
+	- compatible-name: The name which will be used for
+		matching compatible capes.
+
+- slots: node containing a list of slot nodes (which in the beaglebone
+	case correspond to I2C addresses for dynamically probed capes,
+	or an override slot definition for hardcoded capes.
+	- eeprom: Contains the phandle beaglebone's cape i2c eeprom.
+
+	It is possible to define override slots that will be activated
+	when the baseboard matches, and/or if supplied on the kernel command
+	line and/or when dynamically requested on runtime.
+	In that case the slot is marked with
+	- ti,cape-override: Marks a slot override.
+	- compatible: any of the "runtime", "kernel", or any compatible-name
+	  on a matching baseboardmap node.
+	- Any of the eeprom-format-revision, board-name, version, manufacturer,
+	  part-number, number-of-pins, serial-number, pin-usage, vdd-3v3exp,
+	  vdd-5v, sys-5v, dc-supplied properties which fill in the simulated
+	  cape's EEPROM fields. The part-number field is required, the rest
+	  are optional taking into default values.
+
+- capemaps: node contains list of cape mappings, which allow converting
+	from a part-number & version tuple to the filename of the dtbo file.
+	- part-number: part number contained in the EEPROM
+	- version node containing a
+		- version: specific version to map to
+		- dtbo: name of the dtbo file 
+
+Example:
+bone_capemgr {
+	compatible = "ti,bone-capemgr";
+	status = "okay";
+
+	eeprom = <&baseboard_eeprom>;
+
+	baseboardmaps {
+		baseboard_beaglebone: board@0 {
+			board-name = "A335BONE";
+			compatible-name = "ti,beaglebone";
+		};
+	};
+
+	slots {
+		slot@0 {
+			eeprom = <&cape_eeprom0>;
+		};
+
+		slot@1 {
+			eeprom = <&cape_eeprom1>;
+		};
+
+		slot@2 {
+			eeprom = <&cape_eeprom2>;
+		};
+
+		slot@3 {
+			eeprom = <&cape_eeprom3>;
+		};
+	};
+
+	/* mapping between board names and dtb objects */
+	capemaps {
+		/* Weather cape */
+		cape@0 {
+			part-number = "BB-BONE-WTHR-01";
+			version@00A0 {
+				version = "00A0";
+				dtbo = "cape-bone-weather-00A0.dtbo";
+			};
+		};
+	};
+};
+
+Example of the override syntax when used on a bone compatible foo board.
+
+{
+	...
+
+	baseboardmaps {
+		...
+		baseboard_beaglebone: board@0 {
+			board-name = "A335FOO";
+			compatible-name = "ti,foo";
+		};
+
+		slot@6 {
+			ti,cape-override;
+			compatible = "ti,foo";
+			board-name = "FOO-hardcoded";
+			version = "00A0";
+			manufacturer = "Texas Instruments";
+			part-number = "BB-BONE-FOO-01";
+		};
+	};
+
+};
+
+Example of the same override syntax when used from the kernel command-line:
+
+	capemgr.extra_override=FOO-hardcoded:00A0,FOO-another-hardcoded:00A0
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
index ed271fc..826cc51 100644
--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
@@ -20,8 +20,28 @@ ti,dual-volt: boolean, supports dual voltage cards
 ti,non-removable: non-removable slot (like eMMC)
 ti,needs-special-reset: Requires a special softreset sequence
 ti,needs-special-hs-handling: HSMMC IP needs special setting for handling High Speed
+dmas: DMA controller phandle and DMA request value ordered pair
+One tx and one rx pair is required.
+dma-names: DMA request names. These strings correspond 1:1 with
+the ordered pairs in dmas. The RX request must be "rx" and the
+TX request must be "tx".
+
+Examples:
+
+[hwmod populated DMA resources]
+
+	mmc1: mmc@0x4809c000 {
+		compatible = "ti,omap4-hsmmc";
+		reg = <0x4809c000 0x400>;
+		ti,hwmods = "mmc1";
+		ti,dual-volt;
+		bus-width = <4>;
+		vmmc-supply = <&vmmc>; /* phandle to regulator node */
+		ti,non-removable;
+	};
+
+[generic DMA request binding]
 
-Example:
 	mmc1: mmc@0x4809c000 {
 		compatible = "ti,omap4-hsmmc";
 		reg = <0x4809c000 0x400>;
@@ -30,4 +50,7 @@ Example:
 		bus-width = <4>;
 		vmmc-supply = <&vmmc>; /* phandle to regulator node */
 		ti,non-removable;
+		dmas = <&edma 24
+			&edma 25>;
+		dma-names = "tx", "rx";
 	};
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nor.txt b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
new file mode 100644
index 0000000..420b3ab
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
@@ -0,0 +1,98 @@
+Device tree bindings for NOR flash connect to TI GPMC
+
+NOR flash connected to the TI GPMC (found on OMAP boards) are represented as
+child nodes of the GPMC controller with a name of "nor".
+
+All timing relevant properties as well as generic GPMC child properties are
+explained in a separate documents. Please refer to
+Documentation/devicetree/bindings/bus/ti-gpmc.txt
+
+Required properties:
+- bank-width: 		Width of NOR flash in bytes. GPMC supports 8-bit and
+			16-bit devices and so must be either 1 or 2 bytes.
+- compatible:		Documentation/devicetree/bindings/mtd/mtd-physmap.txt
+- gpmc,cs-on-ns:		Chip-select assertion time
+- gpmc,cs-rd-off-ns:	Chip-select de-assertion time for reads
+- gpmc,cs-wr-off-ns:	Chip-select de-assertion time for writes
+- gpmc,oe-on-ns:	Output-enable assertion time
+- gpmc,oe-off-ns:	Output-enable de-assertion time
+- gpmc,we-on-ns		Write-enable assertion time
+- gpmc,we-off-ns:	Write-enable de-assertion time
+- gpmc,access-ns:	Start cycle to first data capture (read access)
+- gpmc,rd-cycle-ns:	Total read cycle time
+- gpmc,wr-cycle-ns:	Total write cycle time
+- linux,mtd-name:	Documentation/devicetree/bindings/mtd/mtd-physmap.txt
+- reg:			Chip-select, base address (relative to chip-select)
+			and size of NOR flash. Note that base address will be
+			typically 0 as this is the start of the chip-select.
+
+Optional properties:
+- gpmc,XXX		Additional GPMC timings and settings parameters. See
+			Documentation/devicetree/bindings/bus/ti-gpmc.txt
+
+Optional properties for partiton table parsing:
+- #address-cells: should be set to 1
+- #size-cells: should be set to 1
+
+Example:
+
+gpmc: gpmc@6e000000 {
+	compatible = "ti,omap3430-gpmc", "simple-bus";
+	ti,hwmods = "gpmc";
+	reg = <0x6e000000 0x1000>;
+	interrupts = <20>;
+	gpmc,num-cs = <8>;
+	gpmc,num-waitpins = <4>;
+	#address-cells = <2>;
+	#size-cells = <1>;
+
+	ranges = <0 0 0x10000000 0x08000000>;
+
+	nor@0,0 {
+		compatible = "cfi-flash";
+		linux,mtd-name= "intel,pf48f6000m0y1be";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0 0 0x08000000>;
+		bank-width = <2>;
+
+		gpmc,mux-add-data;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <186>;
+		gpmc,cs-wr-off-ns = <186>;
+		gpmc,adv-on-ns = <12>;
+		gpmc,adv-rd-off-ns = <48>;
+		gpmc,adv-wr-off-ns = <48>;
+		gpmc,oe-on-ns = <54>;
+		gpmc,oe-off-ns = <168>;
+		gpmc,we-on-ns = <54>;
+		gpmc,we-off-ns = <168>;
+		gpmc,rd-cycle-ns = <186>;
+		gpmc,wr-cycle-ns = <186>;
+		gpmc,access-ns = <114>;
+		gpmc,page-burst-access-ns = <6>;
+		gpmc,bus-turnaround-ns = <12>;
+		gpmc,cycle2cycle-delay-ns = <18>;
+		gpmc,wr-data-mux-bus-ns = <90>;
+		gpmc,wr-access-ns = <186>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-diffcsen;
+
+		partition@0 {
+			label = "bootloader-nor";
+			reg = <0 0x40000>;
+		};
+		partition@0x40000 {
+			label = "params-nor";
+			reg = <0x40000 0x40000>;
+		};
+		partition@0x80000 {
+			label = "kernel-nor";
+			reg = <0x80000 0x200000>;
+		};
+		partition@0x280000 {
+			label = "filesystem-nor";
+			reg = <0x240000 0x7d80000>;
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-onenand.txt b/Documentation/devicetree/bindings/mtd/gpmc-onenand.txt
new file mode 100644
index 0000000..b752942
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/gpmc-onenand.txt
@@ -0,0 +1,46 @@
+Device tree bindings for GPMC connected OneNANDs
+
+GPMC connected OneNAND (found on OMAP boards) are represented as child nodes of
+the GPMC controller with a name of "onenand".
+
+All timing relevant properties as well as generic gpmc child properties are
+explained in a separate documents - please refer to
+Documentation/devicetree/bindings/bus/ti-gpmc.txt
+
+Required properties:
+
+ - reg:			The CS line the peripheral is connected to
+ - gpmc,device-width	Width of the ONENAND device connected to the GPMC
+			in bytes. Must be 1 or 2.
+
+Optional properties:
+
+ - dma-channel:		DMA Channel index
+
+For inline partiton table parsing (optional):
+
+ - #address-cells: should be set to 1
+ - #size-cells: should be set to 1
+
+Example for an OMAP3430 board:
+
+	gpmc: gpmc@6e000000 {
+		compatible = "ti,omap3430-gpmc";
+		ti,hwmods = "gpmc";
+		reg = <0x6e000000 0x1000000>;
+		interrupts = <20>;
+		gpmc,num-cs = <8>;
+		gpmc,num-waitpins = <4>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+
+		onenand@0 {
+			reg = <0 0 0>; /* CS0, offset 0 */
+			gpmc,device-width = <2>;
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			/* partitions go here */
+		};
+	};
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 6ddd028..d46b293 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -20,6 +20,7 @@ Required properties:
 - cpts_clock_shift	: Denominator to convert input clock ticks into nanoseconds
 - phy_id		: Specifies slave phy id
 - mac-address		: Specifies slave MAC address
+- disable-napi		: Disables driver NAPI
 
 Optional properties:
 - ti,hwmods		: Must be "cpgmac0"
diff --git a/Documentation/devicetree/bindings/net/gpmc-eth.txt b/Documentation/devicetree/bindings/net/gpmc-eth.txt
new file mode 100644
index 0000000..24cb4e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/gpmc-eth.txt
@@ -0,0 +1,97 @@
+Device tree bindings for Ethernet chip connected to TI GPMC
+
+Besides being used to interface with external memory devices, the
+General-Purpose Memory Controller can be used to connect Pseudo-SRAM devices
+such as ethernet controllers to processors using the TI GPMC as a data bus.
+
+Ethernet controllers connected to TI GPMC are represented as child nodes of
+the GPMC controller with an "ethernet" name.
+
+All timing relevant properties as well as generic GPMC child properties are
+explained in a separate documents. Please refer to
+Documentation/devicetree/bindings/bus/ti-gpmc.txt
+
+For the properties relevant to the ethernet controller connected to the GPMC
+refer to the binding documentation of the device. For example, the documentation
+for the SMSC 911x is Documentation/devicetree/bindings/net/smsc911x.txt
+
+Child nodes need to specify the GPMC bus address width using the "bank-width"
+property but is possible that an ethernet controller also has a property to
+specify the I/O registers address width. Even when the GPMC has a maximum 16-bit
+address width, it supports devices with 32-bit word registers.
+For example with an SMSC LAN911x/912x controller connected to the TI GPMC on an
+OMAP2+ board, "bank-width = <2>;" and "reg-io-width = <4>;".
+
+Required properties:
+- bank-width: 		Address width of the device in bytes. GPMC supports 8-bit
+			and 16-bit devices and so must be either 1 or 2 bytes.
+- compatible:		Compatible string property for the ethernet child device.
+- gpmc,cs-on:		Chip-select assertion time
+- gpmc,cs-rd-off:	Chip-select de-assertion time for reads
+- gpmc,cs-wr-off:	Chip-select de-assertion time for writes
+- gpmc,oe-on:		Output-enable assertion time
+- gpmc,oe-off		Output-enable de-assertion time
+- gpmc,we-on:		Write-enable assertion time
+- gpmc,we-off:		Write-enable de-assertion time
+- gpmc,access:		Start cycle to first data capture (read access)
+- gpmc,rd-cycle:	Total read cycle time
+- gpmc,wr-cycle:	Total write cycle time
+- reg:			Chip-select, base address (relative to chip-select)
+			and size of the memory mapped for the device.
+			Note that base address will be typically 0 as this
+			is the start of the chip-select.
+
+Optional properties:
+- gpmc,XXX		Additional GPMC timings and settings parameters. See
+			Documentation/devicetree/bindings/bus/ti-gpmc.txt
+
+Example:
+
+gpmc: gpmc@6e000000 {
+	compatible = "ti,omap3430-gpmc";
+	ti,hwmods = "gpmc";
+	reg = <0x6e000000 0x1000>;
+	interrupts = <20>;
+	gpmc,num-cs = <8>;
+	gpmc,num-waitpins = <4>;
+	#address-cells = <2>;
+	#size-cells = <1>;
+
+	ranges = <5 0 0x2c000000 0x1000000>;
+
+	ethernet@5,0 {
+		compatible = "smsc,lan9221", "smsc,lan9115";
+		reg = <5 0 0xff>;
+		bank-width = <2>;
+
+		gpmc,mux-add-data;
+		gpmc,cs-on = <0>;
+		gpmc,cs-rd-off = <186>;
+		gpmc,cs-wr-off = <186>;
+		gpmc,adv-on = <12>;
+		gpmc,adv-rd-off = <48>;
+		gpmc,adv-wr-off = <48>;
+		gpmc,oe-on = <54>;
+		gpmc,oe-off = <168>;
+		gpmc,we-on = <54>;
+		gpmc,we-off = <168>;
+		gpmc,rd-cycle = <186>;
+		gpmc,wr-cycle = <186>;
+		gpmc,access = <114>;
+		gpmc,page-burst-access = <6>;
+		gpmc,bus-turnaround = <12>;
+		gpmc,cycle2cycle-delay = <18>;
+		gpmc,wr-data-mux-bus = <90>;
+		gpmc,wr-access = <186>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-diffcsen;
+
+		interrupt-parent = <&gpio6>;
+		interrupts = <16>;
+		vmmc-supply = <&vddvario>;
+		vmmc_aux-supply = <&vdd33a>;
+		reg-io-width = <4>;
+
+		smsc,save-mac-address;
+	};
+};
diff --git a/Documentation/devicetree/bindings/pps/pps-gpio.txt b/Documentation/devicetree/bindings/pps/pps-gpio.txt
new file mode 100644
index 0000000..40bf9c3
--- /dev/null
+++ b/Documentation/devicetree/bindings/pps/pps-gpio.txt
@@ -0,0 +1,20 @@
+Device-Tree Bindings for a PPS Signal on GPIO
+
+These properties describe a PPS (pulse-per-second) signal connected to
+a GPIO pin.
+
+Required properties:
+- compatible: should be "pps-gpio"
+- gpios: one PPS GPIO in the format described by ../gpio/gpio.txt
+
+Optional properties:
+- assert-falling-edge: when present, assert is indicated by a falling edge
+                       (instead of by a rising edge)
+
+Example:
+	pps {
+		compatible = "pps-gpio";
+		gpios = <&gpio2 6 0>;
+
+		assert-falling-edge;
+	};
diff --git a/Documentation/devicetree/bindings/rtc/rtc-omap.txt b/Documentation/devicetree/bindings/rtc/rtc-omap.txt
index b47aa41..8d9f4f9 100644
--- a/Documentation/devicetree/bindings/rtc/rtc-omap.txt
+++ b/Documentation/devicetree/bindings/rtc/rtc-omap.txt
@@ -6,6 +6,10 @@ Required properties:
 - interrupts: rtc timer, alarm interrupts in order
 - interrupt-parent: phandle for the interrupt controller
 
+Optional properties:
+- ti,system-power-controller: Telling whether or not rtc is controlling
+  the system power.
+
 Example:
 
 rtc@1c23000 {
@@ -14,4 +18,5 @@ rtc@1c23000 {
 	interrupts = <19
 		      19>;
 	interrupt-parent = <&intc>;
+	ti,system-power-controller;
 };
diff --git a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
new file mode 100644
index 0000000..25f7180
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
@@ -0,0 +1,53 @@
+* Texas Instruments SoC audio setups with TLV320AIC3X Codec
+
+Required properties:
+- compatible :
+	"ti,dm365-voice-codec-audio"	: for DM365 platforms with Voice Codec
+	"ti,da830-evm-audio"		: for DM365/DA8xx/OMAPL1x/AM33xx
+
+- ti,model : The user-visible name of this sound complex.
+- ti,audio-codec : The phandle of the TLV320AIC3x audio codec
+- ti,mcasp-controller : The phandle of the McASP controller
+- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec
+- ti,audio-routing : A list of the connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source. Valid names for sources and
+  sinks are the codec's pins, and the jacks on the board:
+
+  Codec pins:
+
+  * MIC3L
+  * MIC3R
+  * LINE1L
+  * LINE2L
+  * LINE1R
+  * LINE2R
+
+  Board connectors:
+
+  * Headphone Jack
+  * Line Out
+  * Mic Jack
+
+
+Example:
+
+sound {
+	compatible = "ti,da830-evm-audio";
+	ti,model = "DA830 EVM";
+	ti,audio-codec = <&tlv320aic3x>;
+	ti,mcasp-controller = <&mcasp1>;
+	ti,codec-clock-rate = <12000000>;
+	ti,audio-routing =
+		"Headphone Jack",       "HPLOUT",
+		"Headphone Jack",       "HPROUT",
+		"Line Out",             "LLOUT",
+		"Line Out",             "RLOUT",
+		"MIC3L",                "Mic Bias 2V",
+		"MIC3R",                "Mic Bias 2V",
+		"Mic Bias 2V",          "Mic Jack",
+		"LINE1L",               "Line In",
+		"LINE2L",               "Line In",
+		"LINE1R",               "Line In",
+		"LINE2R",               "Line In";
+};
diff --git a/Documentation/devicetree/bindings/spi/omap-spi.txt b/Documentation/devicetree/bindings/spi/omap-spi.txt
index 938809c..3bd8eed 100644
--- a/Documentation/devicetree/bindings/spi/omap-spi.txt
+++ b/Documentation/devicetree/bindings/spi/omap-spi.txt
@@ -10,7 +10,18 @@ Required properties:
 			  input. The default is D0 as input and
 			  D1 as output.
 
-Example:
+Optional properties:
+- dmas: List of DMA controller phandle and DMA request ordered
+	pairs. One tx and one rx pair is required for each chip
+	select.
+- dma-names: List of DMA request names. These strings correspond
+	1:1 with the ordered pairs in dmas. The string naming is
+	to be "rxN" and "txN" for RX and TX requests,
+	respectively, where N equals the chip select number.
+
+Examples:
+
+[hwmod populated DMA resources]
 
 mcspi1: mcspi@1 {
     #address-cells = <1>;
@@ -20,3 +31,18 @@ mcspi1: mcspi@1 {
     ti,spi-num-cs = <4>;
 };
 
+[generic DMA request binding]
+
+mcspi1: mcspi@1 {
+    #address-cells = <1>;
+    #size-cells = <0>;
+    compatible = "ti,omap4-mcspi";
+    ti,hwmods = "mcspi1";
+    ti,spi-num-cs = <2>;
+    dmas = <&edma 42
+	    &edma 43
+	    &edma 44
+	    &edma 45>;
+    dma-names = "tx0", "rx0", "tx1", "rx1";
+};
+
diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
index 29a043e..3f0152b 100644
--- a/Documentation/devicetree/bindings/usb/omap-usb.txt
+++ b/Documentation/devicetree/bindings/usb/omap-usb.txt
@@ -1,8 +1,11 @@
-OMAP GLUE
+OMAP GLUE AND OTHER OMAP SPECIFIC COMPONENTS
 
 OMAP MUSB GLUE
  - compatible : Should be "ti,omap4-musb" or "ti,omap3-musb"
  - ti,hwmods : must be "usb_otg_hs"
+ - ti,has_mailbox : to specify that omap uses an external mailbox
+   (in control module) to communicate with the musb core during device connect
+   and disconnect.
  - multipoint : Should be "1" indicating the musb controller supports
    multipoint. This is a MUSB configuration-specific setting.
  - num_eps : Specifies the number of endpoints. This is also a
@@ -20,6 +23,7 @@ SOC specific device node entry
 usb_otg_hs: usb_otg_hs@4a0ab000 {
 	compatible = "ti,omap4-musb";
 	ti,hwmods = "usb_otg_hs";
+	ti,has_mailbox;
 	multipoint = <1>;
 	num_eps = <16>;
 	ram_bits = <12>;
@@ -31,3 +35,22 @@ Board specific device node entry
 	mode = <3>;
 	power = <50>;
 };
+
+OMAP CONTROL USB
+
+Required properties:
+ - compatible: Should be "ti,omap-control-usb"
+ - reg : Address and length of the register set for the device. It contains
+   the address of "control_dev_conf" and "otghs_control".
+ - reg-names: The names of the register addresses corresponding to the registers
+   filled in "reg".
+ - ti,has_mailbox: This is used to specify if the platform uses mailbox in
+   control module.
+
+omap_control_usb@4a002300 {
+	compatible = "ti,omap-control-usb";
+	reg = <0x4a002300 0x4>,
+	      <0x4a00233c 0x4>;
+	reg-names = "control_dev_conf", "otghs_control";
+	ti,has_mailbox;
+};
diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
index 80d4148..ee14cb7 100644
--- a/Documentation/devicetree/bindings/usb/usb-phy.txt
+++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
@@ -4,14 +4,11 @@ OMAP USB2 PHY
 
 Required properties:
  - compatible: Should be "ti,omap-usb2"
- - reg : Address and length of the register set for the device. Also
-add the address of control module dev conf register until a driver for
-control module is added
+ - reg : Address and length of the register set for the device.
 
 This is usually a subnode of ocp2scp to which it is connected.
 
 usb2phy@4a0ad080 {
 	compatible = "ti,omap-usb2";
-	reg = <0x4a0ad080 0x58>,
-	      <0x4a002300 0x4>;
+	reg = <0x4a0ad080 0x58>;
 };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 902b1b1..cb0209a 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -4,6 +4,7 @@ This isn't an exhaustive list, but you should add new prefixes to it before
 using them to avoid name-space collisions.
 
 ad	Avionic Design GmbH
+adafruit	Adafruit Industries
 adi	Analog Devices, Inc.
 ak	Asahi Kasei Corp.
 amcc	Applied Micro Circuits Corporation (APM, formally AMCC)
@@ -48,7 +49,9 @@ schindler	Schindler
 sil	Silicon Image
 simtek
 sirf	SiRF Technology, Inc.
+sitronix Sitronix Technology Corp.
 snps 	Synopsys, Inc.
+spansion	Spansion, Inc.
 st	STMicroelectronics
 stericsson	ST-Ericsson
 ti	Texas Instruments
diff --git a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
index 1e4fc72..689c7d2 100644
--- a/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
+++ b/Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt
@@ -14,6 +14,8 @@ Required properties:
 Optional properties:
   - pwm-names: a list of names for the PWM devices specified in the
                "pwms" property (see PWM binding[0])
+  - low_threshold_brightness: brightness threshold low level. (get linear
+		 scales in brightness in low end of brightness levels)
 
 [0]: Documentation/devicetree/bindings/pwm/pwm.txt
 
@@ -26,3 +28,22 @@ Example:
 		brightness-levels = <0 4 8 16 32 64 128 255>;
 		default-brightness-level = <6>;
 	};
+
+Example for brightness_threshold_level:
+
+	backlight {
+		compatible	= "pwm-backlight";
+		pwms = <&pwm 0 50000>;
+
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+		low_threshold_brightness = <50>;
+	};
+};
+Note:
+Low threshold support is required to have linear brightness scale from
+0 to max. For some panels, backlight absent on low end of brightness
+scale. So support for Low Threshold been required. So that the scale of
+brightness changed from Low Threshold to Max in scales defined in
+brightness-levels. In this example 20% maximum brightness scale should
+be required to turn on panel backlight.
diff --git a/Documentation/devicetree/bindings/video/display-timing.txt b/Documentation/devicetree/bindings/video/display-timing.txt
new file mode 100644
index 0000000..bf9d82b
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/display-timing.txt
@@ -0,0 +1,109 @@
+display-timing bindings
+=======================
+
+display-timings node
+--------------------
+
+required properties:
+ - none
+
+optional properties:
+ - native-mode: The native mode for the display, in case multiple modes are
+		provided. When omitted, assume the first node is the native.
+
+timing subnode
+--------------
+
+required properties:
+ - hactive, vactive: display resolution
+ - hfront-porch, hback-porch, hsync-len: horizontal display timing parameters
+   in pixels
+   vfront-porch, vback-porch, vsync-len: vertical display timing parameters in
+   lines
+ - clock-frequency: display clock in Hz
+
+optional properties:
+ - hsync-active: hsync pulse is active low/high/ignored
+ - vsync-active: vsync pulse is active low/high/ignored
+ - de-active: data-enable pulse is active low/high/ignored
+ - pixelclk-active: with
+			- active high = drive pixel data on rising edge/
+					sample data on falling edge
+			- active low  = drive pixel data on falling edge/
+					sample data on rising edge
+			- ignored     = ignored
+ - interlaced (bool): boolean to enable interlaced mode
+ - doublescan (bool): boolean to enable doublescan mode
+
+All the optional properties that are not bool follow the following logic:
+    <1>: high active
+    <0>: low active
+    omitted: not used on hardware
+
+There are different ways of describing the capabilities of a display. The
+devicetree representation corresponds to the one commonly found in datasheets
+for displays. If a display supports multiple signal timings, the native-mode
+can be specified.
+
+The parameters are defined as:
+
+  +----------+-------------------------------------+----------+-------+
+  |          |        .                            |          |       |
+  |          |        |vback_porch                 |          |       |
+  |          |        .                            |          |       |
+  +----------#######################################----------+-------+
+  |          #        .                            #          |       |
+  |          #        |                            #          |       |
+  |  hback   #        |                            #  hfront  | hsync |
+  |   porch  #        |       hactive              #  porch   |  len  |
+  |<-------->#<-------+--------------------------->#<-------->|<----->|
+  |          #        |                            #          |       |
+  |          #        |vactive                     #          |       |
+  |          #        |                            #          |       |
+  |          #        .                            #          |       |
+  +----------#######################################----------+-------+
+  |          |        .                            |          |       |
+  |          |        |vfront_porch                |          |       |
+  |          |        .                            |          |       |
+  +----------+-------------------------------------+----------+-------+
+  |          |        .                            |          |       |
+  |          |        |vsync_len                   |          |       |
+  |          |        .                            |          |       |
+  +----------+-------------------------------------+----------+-------+
+
+Example:
+
+	display-timings {
+		native-mode = <&timing0>;
+		timing0: 1080p24 {
+			/* 1920x1080p24 */
+			clock-frequency = <52000000>;
+			hactive = <1920>;
+			vactive = <1080>;
+			hfront-porch = <25>;
+			hback-porch = <25>;
+			hsync-len = <25>;
+			vback-porch = <2>;
+			vfront-porch = <2>;
+			vsync-len = <2>;
+			hsync-active = <1>;
+		};
+	};
+
+Every required property also supports the use of ranges, so the commonly used
+datasheet description with minimum, typical and maximum values can be used.
+
+Example:
+
+	timing1: timing {
+		/* 1920x1080p24 */
+		clock-frequency = <148500000>;
+		hactive = <1920>;
+		vactive = <1080>;
+		hsync-len = <0 44 60>;
+		hfront-porch = <80 88 95>;
+		hback-porch = <100 148 160>;
+		vfront-porch = <0 4 6>;
+		vback-porch = <0 36 50>;
+		vsync-len = <0 5 6>;
+	};
diff --git a/Documentation/devicetree/bindings/video/fb-da8xx.txt b/Documentation/devicetree/bindings/video/fb-da8xx.txt
new file mode 100644
index 0000000..0741f78
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/fb-da8xx.txt
@@ -0,0 +1,37 @@
+TI LCD Controller on DA830/DA850/AM335x SoC's
+
+Required properties:
+- compatible:
+	DA830 - "ti,da830-lcdc"
+	AM335x SoC's - "ti,am3352-lcdc", "ti,da830-lcdc"
+- reg: Address range of lcdc register set
+- interrupts: lcdc interrupt
+- display-timings: typical videomode of lcd panel, represented as child.
+  Refer Documentation/devicetree/bindings/video/display-timing.txt for
+  display timing binding details. If multiple videomodes are mentioned
+  in display timings node, typical videomode has to be mentioned as the
+  native mode or it has to be first child (driver cares only for native
+  videomode).
+
+Example:
+
+lcdc@4830e000 {
+	compatible = "ti,am3352-lcdc", "ti,da830-lcdc";
+	reg =  <0x4830e000 0x1000>;
+	interrupts = <36>;
+	display-timings {
+		800x480p62 {
+			clock-frequency = <30000000>;
+			hactive = <800>;
+			vactive = <480>;
+			hfront-porch = <39>;
+			hback-porch = <39>;
+			hsync-len = <47>;
+			vback-porch = <29>;
+			vfront-porch = <13>;
+			vsync-len = <2>;
+			hsync-active = <1>;
+			vsync-active = <1>;
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/video/ssd1307fb.txt b/Documentation/devicetree/bindings/video/ssd1307fb.txt
index 3d0060c..7a12542 100644
--- a/Documentation/devicetree/bindings/video/ssd1307fb.txt
+++ b/Documentation/devicetree/bindings/video/ssd1307fb.txt
@@ -1,13 +1,17 @@
 * Solomon SSD1307 Framebuffer Driver
 
 Required properties:
-  - compatible: Should be "solomon,ssd1307fb-<bus>". The only supported bus for
-    now is i2c.
+  - compatible: Should be "solomon,<chip>fb-<bus>". The only supported bus for
+    now is i2c, and the supported chips are ssd1306 and ssd1307.
   - 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]
+         specification [0]. Only required for the ssd1307.
   - reset-gpios: Should contain the GPIO used to reset the OLED display
+  - solomon,height: Height in pixel of the screen driven by the controller
+  - solomon,width: Width in pixel of the screen driven by the controller
+  - solomon,page-offset: Offset of pages (band of 8 pixels) that the screen is
+    mapped to.
 
 Optional properties:
   - reset-active-low: Is the reset gpio is active on physical low?
diff --git a/Documentation/devicetree/dt-object-internal.txt b/Documentation/devicetree/dt-object-internal.txt
new file mode 100644
index 0000000..f86d054
--- /dev/null
+++ b/Documentation/devicetree/dt-object-internal.txt
@@ -0,0 +1,295 @@
+Device Tree Dynamic Object format internals
+-------------------------------------------
+
+The Device Tree for most platforms is a static representation of
+the hardware capabilities. This is insufficient for many platforms
+that need to dynamically insert device tree fragments to the
+running kernel's live tree.
+
+This document explains the the device tree object format and the
+modifications made to the device tree compiler, which make it possible.
+
+1. Simplified Problem Definition
+--------------------------------
+
+Assume we have a platform which boots using following simplified device tree.
+
+---- foo.dts -----------------------------------------------------------------
+	/* FOO platform */
+	/ {
+		compatible = "corp,foo";
+
+		/* shared resources */
+		res: res {
+		};
+
+		/* On chip peripherals */
+		ocp: ocp {
+			/* peripherals that are always instantiated */
+			peripheral1 { ... };
+		}
+	};
+---- foo.dts -----------------------------------------------------------------
+
+We have a number of peripherals that after probing (using some undefined method)
+should result in different device tree configuration.
+
+We cannot boot with this static tree because due to the configuration of the
+foo platform there exist multiple conficting peripherals DT fragments.
+
+So for the bar peripheral we would have this:
+
+---- foo+bar.dts -------------------------------------------------------------
+	/* FOO platform + bar peripheral */
+	/ {
+		compatible = "corp,foo";
+
+		/* shared resources */
+		res: res {
+		};
+
+		/* On chip peripherals */
+		ocp: ocp {
+			/* peripherals that are always instantiated */
+			peripheral1 { ... };
+
+			/* bar peripheral */
+			bar {
+				compatible = "corp,bar";
+				... /* various properties and child nodes */
+			}
+		}
+	};
+---- foo+bar.dts -------------------------------------------------------------
+
+While for the baz peripheral we would have this:
+
+---- foo+baz.dts -------------------------------------------------------------
+	/* FOO platform + baz peripheral */
+	/ {
+		compatible = "corp,foo";
+
+		/* shared resources */
+		res: res {
+			/* baz resources */
+			baz_res: res_baz { ... };
+		};
+
+		/* On chip peripherals */
+		ocp: ocp {
+			/* peripherals that are always instantiated */
+			peripheral1 { ... };
+
+			/* baz peripheral */
+			baz {
+				compatible = "corp,baz";
+				/* reference to another point in the tree */
+				ref-to-res = <&baz_res>;
+				... /* various properties and child nodes */
+			}
+		}
+	};
+---- foo+baz.dts -------------------------------------------------------------
+
+We note that the baz case is more complicated, since the baz peripheral needs to
+reference another node in the DT tree.
+
+2. Device Tree Object Format Requirements
+-----------------------------------------
+
+Since the device tree is used for booting a number of very different hardware
+platforms it is imperative that we tread very carefully.
+
+2.a) No changes to the Device Tree binary format. We cannot modify the tree
+format at all and all the information we require should be encoded using device
+tree itself. We can add nodes that can be safely ignored by both bootloaders and
+the kernel.
+
+2.b) Changes to the DTS source format should be absolutely minimal, and should
+only be needed for the DT fragment definitions, and not the base boot DT.
+
+2.c) An explicit option should be used to instruct DTC to generate the required
+information needed for object resolution. Platforms that don't use the
+dynamic object format can safely ignore it.
+
+2.d) Finally, DT syntax changes should be kept to a minimum. It should be
+possible to express everything using the existing DT syntax.
+
+3. Implementation
+-----------------
+
+The basic unit of addressing in Device Tree is the phandle. Turns out it's
+relatively simple to extend the way phandles are generated and referenced
+so that it's possible to dynamically convert symbolic references (labels)
+to phandle values.
+
+We can roughly divide the operation into two steps.
+
+3.a) Compilation of the base board DTS file using the '-@' option
+generates a valid DT blob with an added __symbols__ node at the root node,
+containing a list of all nodes that are marked with a label.
+
+Using the foo.dts file above the following node will be generated;
+
+$ dtc -@ -O dtb -o foo.dtb -b 0 foo.dts
+$ fdtdump foo.dtb
+...
+/ {
+	...
+	res {
+		...
+		linux,phandle = <0x00000001>;
+		phandle = <0x00000001>;
+		...
+	};
+	ocp {
+		...
+		linux,phandle = <0x00000002>;
+		phandle = <0x00000002>;
+		...
+	};
+	__symbols__ {
+		res="/res";
+		ocp="/ocp";
+	};
+};
+
+Notice that all the nodes that had a label have been recorded, and that
+phandles have been generated for them.
+
+This blob can be used to boot the board normally, the __symbols__ node will
+be safely ignored both by the bootloader and the kernel (the only loss will
+be a few bytes of memory and disk space).
+
+3.b) The Device Tree fragments must be compiled with the same option but they
+must also have a tag (/plugin/) that allows undefined references to labels
+that are not present at compilation time to be recorded so that the runtime
+loader can fix them.
+
+So the bar peripheral's DTS format would be of the form:
+
+/plugin/;	/* allow undefined label references and record them */
+/ {
+	....	/* various properties for loader use; i.e. part id etc. */
+	fragment@0 {
+		target = <&ocp>;
+		__overlay__ {
+			/* bar peripheral */
+			bar {
+				compatible = "corp,bar";
+				... /* various properties and child nodes */
+			}
+		};
+	};
+};
+
+Note that there's a target property that specifies the location where the
+contents of the overlay node will be placed, and it references the label
+in the foo.dts file.
+
+$ dtc -@ -O dtb -o bar.dtbo -b 0 bar.dts
+$ fdtdump bar.dtbo
+...
+/ {
+	... /* properties */
+	fragment@0 {
+		target = <0xdeadbeef>;
+		__overlay__ {
+			bar {
+				compatible = "corp,bar";
+				... /* various properties and child nodes */
+			}
+		};
+	};
+	__fixups__ {
+	    ocp = "/fragment@0:target:0";
+	};
+};
+
+No __symbols__ has been generated (no label in bar.dts).
+Note that the target's ocp label is undefined, so the phandle handle
+value is filled with the illegal value '0xdeadbeef', while a __fixups__
+node has been generated, which marks the location in the tree where 
+the label lookup should store the runtime phandle value of the ocp node.
+
+The format of the __fixups__ node entry is 
+
+	<label> = "<local-full-path>:<property-name>:<offset>";
+
+<label> 		Is the label we're referring
+<local-full-path>	Is the full path of the node the reference is
+<property-name>		Is the name of the property containing the
+			reference
+<offset>		The offset (in bytes) of where the property's
+			phandle value is located.
+
+Doing the same with the baz peripheral's DTS format is a little bit more 
+involved, since baz contains references to local labels which require
+local fixups.
+
+/plugin/;	/* allow undefined label references and record them */
+/ {
+	....	/* various properties for loader use; i.e. part id etc. */
+	fragment@0 {
+		target = <&res>;
+		__overlay__ {
+			/* baz resources */
+			baz_res: res_baz { ... };
+		};
+	};
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			/* baz peripheral */
+			baz {
+				compatible = "corp,baz";
+				/* reference to another point in the tree */
+				ref-to-res = <&baz_res>;
+				... /* various properties and child nodes */
+			}
+		};
+	};
+};
+
+Note that &bar_res reference.
+
+$ dtc -@ -O dtb -o baz.dtbo -b 0 baz.dts
+$ fdtdump baz.dtbo
+...
+/ {
+	... /* properties */
+	fragment@0 {
+		target = <0xdeadbeef>;
+		__overlay__ {
+			res_baz { 
+				....
+				linux,phandle = <0x00000001>;
+				phandle = <0x00000001>;
+			};
+		};
+	};
+	fragment@1 {
+		target = <0xdeadbeef>;
+		__overlay__ {
+			baz {
+				compatible = "corp,baz";
+				... /* various properties and child nodes */
+				res=<0x00000001>;
+			}
+		};
+	};
+	__fixups__ {
+		res = "/fragment@0:target:0";
+		ocp = "/fragment@1:target:0";
+	};
+	__local_fixups__ {
+		fixup = </fragment@1/__overlay__/baz:res:0>;
+	};
+};
+
+This is similar to the bar case, but the reference of a local label by the
+baz node generates a __local_fixups__ entry that records the place that the
+local reference is being made. Since phandles are allocated starting at 1
+the run time loader must apply an offset to each phandle in every dynamic
+DT object loaded. The __local_fixups__ node records the place of every
+local reference so that the loader can apply the offset.
diff --git a/Documentation/devicetree/dynamic-resolution-notes.txt b/Documentation/devicetree/dynamic-resolution-notes.txt
new file mode 100644
index 0000000..0b396c4
--- /dev/null
+++ b/Documentation/devicetree/dynamic-resolution-notes.txt
@@ -0,0 +1,25 @@
+Device Tree Dynamic Resolver Notes
+----------------------------------
+
+This document describes the implementation of the in-kernel
+Device Tree resolver, residing in drivers/of/resolver.c and is a
+companion document to Documentation/devicetree/dt-object-internal.txt[1]
+
+How the resolver works
+----------------------
+
+The resolver is given as an input an arbitrary tree compiled with the
+proper dtc option and having a /plugin/ tag. This generates the
+appropriate __fixups__ & __local_fixups__ nodes as described in [1].
+
+In sequence the resolver works by the following steps:
+
+1. Get the maximum device tree phandle value from the live tree + 1.
+2. Adjust all the local phandles of the tree to resolve by that amount.
+3. Using the __local__fixups__ node information adjust all local references
+   by the same amount.
+4. For each property in the __fixups__ node locate the node it references
+   in the live tree. This is the label used to tag the node.
+5. Retrieve the phandle of the target of the fixup.
+5. For each fixup in the property locate the node:property:offset location
+   and replace it with the phandle value.
diff --git a/Documentation/devicetree/overlay-notes.txt b/Documentation/devicetree/overlay-notes.txt
new file mode 100644
index 0000000..5289cbb
--- /dev/null
+++ b/Documentation/devicetree/overlay-notes.txt
@@ -0,0 +1,179 @@
+Device Tree Overlay Notes
+-------------------------
+
+This document describes the implementation of the in-kernel
+device tree overlay functionality residing in drivers/of/overlay.c and is a
+companion document to Documentation/devicetree/dt-object-internal.txt[1] &
+Documentation/devicetree/dynamic-resolution-notes.txt[2]
+
+How overlays work
+-----------------
+
+A Device Tree's overlay purpose is to modify the kernel's live tree, and
+have the modification affecting the state of the the kernel in a way that
+is reflecting the changes.
+Since the kernel mainly deals with devices, any new device node that result
+in an active device should have it created while if the device node is either
+disabled or removed all together, the affected device should be deregistered.
+
+Lets take an example where we have a foo board with the following base tree
+which is taken from [1].
+
+---- foo.dts -----------------------------------------------------------------
+	/* FOO platform */
+	/ {
+		compatible = "corp,foo";
+
+		/* shared resources */
+		res: res {
+		};
+
+		/* On chip peripherals */
+		ocp: ocp {
+			/* peripherals that are always instantiated */
+			peripheral1 { ... };
+		}
+	};
+---- foo.dts -----------------------------------------------------------------
+
+The overlay bar.dts, when loaded (and resolved as described in [2]) should
+
+---- bar.dts -----------------------------------------------------------------
+/plugin/;	/* allow undefined label references and record them */
+/ {
+	....	/* various properties for loader use; i.e. part id etc. */
+	fragment@0 {
+		target = <&ocp>;
+		__overlay__ {
+			/* bar peripheral */
+			bar {
+				compatible = "corp,bar";
+				... /* various properties and child nodes */
+			}
+		};
+	};
+};
+---- bar.dts -----------------------------------------------------------------
+
+result in foo+bar.dts
+
+---- foo+bar.dts -------------------------------------------------------------
+	/* FOO platform + bar peripheral */
+	/ {
+		compatible = "corp,foo";
+
+		/* shared resources */
+		res: res {
+		};
+
+		/* On chip peripherals */
+		ocp: ocp {
+			/* peripherals that are always instantiated */
+			peripheral1 { ... };
+
+			/* bar peripheral */
+			bar {
+				compatible = "corp,bar";
+				... /* various properties and child nodes */
+			}
+		}
+	};
+---- foo+bar.dts -------------------------------------------------------------
+
+As a result of the the overlay, a new device node (bar) has been created
+so a bar platform device will be registered and if a matching device driver
+is loaded the device will be created as expected.
+
+Overlay in-kernel API
+---------------------
+
+The steps typically required to get an overlay to work are as follows:
+
+1. Use of_build_overlay_info() to create an array of initialized and
+ready to use of_overlay_info structures.
+2. Call of_overlay() to apply the overlays declared in the array.
+3. If the overlay needs to be removed, call of_overlay_revert().
+4. Finally release the memory taken by the overlay info array by
+of_free_overlay_info().
+
+/**
+ * of_build_overlay_info	- Build an overlay info array
+ * @tree:	Device node containing all the overlays
+ * @cntp:	Pointer to where the overlay info count will be help
+ * @ovinfop:	Pointer to the pointer of an overlay info structure.
+ *
+ * Helper function that given a tree containing overlay information,
+ * allocates and builds an overlay info array containing it, ready
+ * for use using of_overlay.
+ *
+ * Returns 0 on success with the @cntp @ovinfop pointers valid,
+ * while on error a negative error value is returned.
+ */
+int of_build_overlay_info(struct device_node *tree,
+		int *cntp, struct of_overlay_info **ovinfop);
+
+/**
+ * of_free_overlay_info	- Free an overlay info array
+ * @count:	Number of of_overlay_info's
+ * @ovinfo_tab:	Array of overlay_info's to free
+ *
+ * Releases the memory of a previously allocate ovinfo array
+ * by of_build_overlay_info.
+ * Returns 0, or an error if the arguments are bogus.
+ */
+int of_free_overlay_info(int count, struct of_overlay_info *ovinfo_tab);
+
+/**
+ * of_overlay	- Apply @count overlays pointed at by @ovinfo_tab
+ * @count:	Number of of_overlay_info's
+ * @ovinfo_tab:	Array of overlay_info's to apply
+ *
+ * Applies the overlays given, while handling all error conditions
+ * appropriately. Either the operation succeeds, or if it fails the
+ * live tree is reverted to the state before the attempt.
+ * Returns 0, or an error if the overlay attempt failed.
+ */
+int of_overlay(int count, struct of_overlay_info *ovinfo_tab);
+
+/**
+ * of_overlay_revert	- Revert a previously applied overlay
+ * @count:	Number of of_overlay_info's
+ * @ovinfo_tab:	Array of overlay_info's to apply
+ *
+ * Revert a previous overlay. The state of the live tree
+ * is reverted to the one before the overlay.
+ * Returns 0, or an error if the overlay table is not given.
+ */
+int of_overlay_revert(int count, struct of_overlay_info *ovinfo_tab);
+
+Overlay DTS Format
+------------------
+
+The DTS of an overlay should have the following format:
+
+{
+	/* ignored properties by the overlay */
+
+	fragment@0 {	/* first child node */
+		target=<phandle>;	/* target of the overlay */
+		__overlay__ {
+			property-a;	/* add property-a to the target */
+			-property-b;	/* remove property-b from target */
+			node-a {	/* add to an existing, or create a node-a */
+				...
+			};
+			-node-b {	/* remove an existing node-b */
+				...
+			};
+		};
+	}
+	fragment@1 {	/* second child node */
+		...
+	};
+	/* more fragments follow */
+}
+
+It should be noted that the DT overlay format described is the one expected
+by the of_build_overlay_info() function, which is a helper function. There
+is nothing stopping someone coming up with his own DTS format and that will
+end up filling in the fields of the of_overlay_info array. 
diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt
index 7d2b4c9..b349d16 100644
--- a/Documentation/pwm.txt
+++ b/Documentation/pwm.txt
@@ -45,6 +45,52 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns);
 
 To start/stop toggling the PWM output use pwm_enable()/pwm_disable().
 
+Using PWMs with the sysfs interface
+-----------------------------------
+
+You have to enable CONFIG_PWM_SYSFS in your kernel configuration to use
+the sysfs interface. It is exposed at /sys/class/pwm/. If there are pwm
+drivers loaded and these drivers successfully probed a chip, this chip
+is exported as pwmchipX . Note that a single driver can probe multiple chips.
+Inside the directory you can read these properties:
+
+base - This is the linux global start where the chips pwm channels get
+exposed.
+
+npwm - This is the number of pwm channels this chip supports.
+
+If you want to start using a pwm channel with sysfs first you have to
+export it. If you are finished with it and want to free the pwm for other
+uses, you can unexport it:
+
+export - Write the global pwm channel number to this file to start using
+the channel with sysfs.
+
+unexport - Write the global pwm channel number of the channel you are finshed
+with to this file to make the channel available for other uses.
+
+Once a pwm is exported a pwmX (X ranging from 0 to MAX_PWMS) directory appears
+with the following read/write properties inside to control the pwm:
+
+duty_ns - Write the number of nanoseconds the active portion of the pwm period
+should last to this file. This can not be longer than the period_ns.
+
+period_ns - Write the length of the pwm period in nanoseconds to this file.
+This includes the active and inactive portion of the pwm period and can not
+be smaller than duty_ns.
+
+polarity - The normal behaviour is to put out a high for the active portion of
+the pwm period. Write a 1 to this file to inverse the signal and output a low
+on the active portion. Write a 0 to switch back to the normal behaviour. The
+polarity can only be changed if the pwm is not running. This file is only
+visible if the underlying driver/device supports changing the polarity.
+
+run - Write a 1 to this file to start the pwm signal generation, write a 0 to
+stop it. Set your desired period_ns, duty_ns and polarity before starting the
+pwm.
+
+It is recommend to set the period_ns at first and duty_ns after that.
+
 Implementing a PWM driver
 -------------------------
 
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 67874b8..7637d31 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -932,6 +932,7 @@ config ARCH_DAVINCI
 	select GENERIC_IRQ_CHIP
 	select HAVE_IDE
 	select NEED_MACH_GPIO_H
+	select TI_PRIV_EDMA
 	select USE_OF
 	select ZONE_DMA
 	help
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 30c443c..d5935c0 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -275,6 +275,10 @@ ifeq ($(CONFIG_USE_OF),y)
 KBUILD_DTBS := dtbs
 endif
 
+ifeq ($(CONFIG_OF_RESOLVE),y)
+DTC_FLAGS += -@
+endif
+
 all:	$(KBUILD_IMAGE) $(KBUILD_DTBS)
 
 boot := arch/arm/boot
@@ -291,11 +295,14 @@ zImage Image xipImage bootpImage uImage: vmlinux
 zinstall uinstall install: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
+uImage-dtb.%: scripts
+	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
 %.dtb: scripts
-	$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@
+	$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) DTC_FLAGS=$(DTC_FLAGS) $(boot)/dts/$@
 
 dtbs: scripts
-	$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) dtbs
+	$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) DTC_FLAGS=$(DTC_FLAGS) dtbs
 
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index abfce28..bedc651 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -55,6 +55,13 @@ $(obj)/zImage:	$(obj)/compressed/vmlinux FORCE
 	$(call if_changed,objcopy)
 	@$(kecho) '  Kernel: $@ is ready'
 
+$(obj)/zImage-dtb.%:	$(obj)/dts/%.dtb $(obj)/zImage
+	cat $(obj)/zImage $< > $@
+
+endif
+
+ifeq ($(CONFIG_OF_RESOLVE),y)
+DTC_FLAGS += -@
 endif
 
 ifneq ($(LOADADDR),)
@@ -80,6 +87,10 @@ $(obj)/uImage:	$(obj)/zImage FORCE
 	$(call if_changed,uimage)
 	@$(kecho) '  Image $@ is ready'
 
+$(obj)/uImage-dtb.%:	$(obj)/zImage-dtb.% FORCE
+	$(call if_changed,uimage)
+	@echo '  Image $@ is ready'
+
 $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
 	$(Q)$(MAKE) $(build)=$(obj)/bootp $@
 	@:
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 5cad8a6..12edc8c 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -121,7 +121,7 @@ KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
 
 ccflags-y := -fpic -fno-builtin -I$(obj)
-asflags-y := -Wa,-march=all -DZIMAGE
+asflags-y := -Wa,-march=armv7a -DZIMAGE
 
 # Supply kernel BSS size to the decompressor via a linker symbol.
 KBSS_SZ = $(shell $(CROSS_COMPILE)size $(obj)/../../../../vmlinux | \
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 5ebb44f..9da016f 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -113,7 +113,9 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
 	omap5-evm.dtb \
 	am335x-evm.dtb \
 	am335x-evmsk.dtb \
-	am335x-bone.dtb
+	am335x-bone.dtb \
+	am335x-boneblack.dtb \
+	am335x-tester.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 \
diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
new file mode 100644
index 0000000..c450d0b
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
@@ -0,0 +1,512 @@
+/*
+ * 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/ "am33xx.dtsi"
+
+/ {
+	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 = <&userled_pins>;
+
+		userled_pins: pinmux_userled_pins {
+			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 */
+			>;
+		};
+		i2c0_pins: pinmux_i2c0_pins {
+			pinctrl-single,pins = <
+				0x188 0x70 	/* i2c0_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */
+				0x18c 0x70	/* i2c0_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */
+			>;
+		};
+		i2c2_pins: pinmux_i2c2_pins {
+			pinctrl-single,pins = <
+				0x178 0x73 	/* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+				0x17c 0x73	/* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+			>;
+		};
+	};
+
+	ocp: ocp {
+
+		uart1: serial@44e09000 {
+			status = "okay";
+		};
+
+		gpio-leds {
+			compatible = "gpio-leds";
+			pinctrl-names = "default";
+			pinctrl-0 = <&userled_pins>;
+
+			led0 {
+				label = "beaglebone:green:usr0";
+				gpios = <&gpio2 21 0>;
+				linux,default-trigger = "heartbeat";
+				default-state = "off";
+			};
+
+			led1 {
+				label = "beaglebone:green:usr1";
+				gpios = <&gpio2 22 0>;
+				linux,default-trigger = "mmc0";
+				default-state = "off";
+			};
+
+			led2 {
+				label = "beaglebone:green:usr2";
+				gpios = <&gpio2 23 0>;
+				linux,default-trigger = "cpu0";
+				default-state = "off";
+			};
+
+			led3 {
+				label = "beaglebone:green:usr3";
+				gpios = <&gpio2 24 0>;
+				default-state = "off";
+				linux,default-trigger = "mmc1";
+			};
+		};
+
+		rtc@44e3e000 {
+			ti,system-power-controller;
+		};
+	};
+
+	bone_capemgr {
+		compatible = "ti,bone-capemgr";
+		status = "okay";
+
+		eeprom = <&baseboard_eeprom>;
+
+		baseboardmaps {
+			baseboard_beaglebone: board@0 {
+				board-name = "A335BONE";
+				compatible-name = "ti,beaglebone";
+			};
+
+			baseboard_beaglebone_black: board@1 {
+				board-name = "A335BNLT";
+				compatible-name = "ti,beaglebone-black";
+			};
+		};
+
+		slots {
+			slot@0 {
+				eeprom = <&cape_eeprom0>;
+			};
+
+			slot@1 {
+				eeprom = <&cape_eeprom1>;
+			};
+
+			slot@2 {
+				eeprom = <&cape_eeprom2>;
+			};
+
+			slot@3 {
+				eeprom = <&cape_eeprom3>;
+			};
+
+			/* geiger cape version A0 without an EEPROM */
+			slot@5 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "Bone-Geiger";
+				version = "00A0";
+				manufacturer = "Geiger Inc.";
+				part-number = "BB-BONE-GEIGER";
+			};
+
+			/* Nixie cape version A0 without an EEPROM */
+			slot@7 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "Bone-Nixie";
+				version = "00A0";
+				manufacturer = "Ranostay Industries";
+				part-number = "BB-BONE-NIXIE";
+			};
+
+			/* adafruit 1.8" TFT prototype cape */
+			slot@8 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "Bone-TFT";
+				version = "00A0";
+				manufacturer = "Adafruit";
+				part-number = "BB-BONE-TFT-01";
+			};
+
+			/* adafruit RTC DS1307 prototype cape */
+			slot@9 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "Bone-RTC";
+				version = "00A0";
+				manufacturer = "Adafruit";
+				part-number = "BB-BONE-RTC-01";
+			};
+
+			slot@10 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "Bone-Hexy";
+				version = "00A0";
+				manufacturer = "Koen Kooi";
+				part-number = "BB-BONE-HEXY-01";
+			};
+			/* MRF24J40 Cape Override */
+			slot@11 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "Bone-MRF24J40";
+				version = "00A0";
+				manufacturer = "Signal 11 Software";
+				part-number = "BB-BONE-MRF24J40";
+			};
+
+			/* RS232 cape */
+			slot@12 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "BB-BONE-RS232";
+				version = "00A0";
+				manufacturer = "Adafruit";
+				part-number = "BB-BONE-RS232-01";
+			};
+
+			/* Beaglebone black has it soldered on */
+			 slot@100 {
+			 	ti,cape-override;
+				priority = <1>;
+			 	compatible = "ti,beaglebone-black";
+			 	board-name = "Bone-LT-eMMC-2G";
+			 	version = "00A0";
+			 	manufacturer = "Texas Instruments";
+			 	part-number = "BB-BONE-EMMC-2G";
+			 };
+
+			/* Beaglebone black has it soldered on */
+			slot@101 {
+				ti,cape-override;
+				priority = <1>;
+				compatible = "ti,beaglebone-black";
+				board-name = "Bone-Black-HDMI";
+				version = "00A0";
+				manufacturer = "Texas Instruments";
+				part-number = "BB-BONELT-HDMI";
+			};
+
+			/* Beaglebone black has it soldered on (but no audio) */
+			slot@102 {
+				ti,cape-override;
+				priority = <2>;
+				compatible = "ti,beaglebone-black";
+				board-name = "Bone-Black-HDMIN";
+				version = "00A0";
+				manufacturer = "Texas Instruments";
+				part-number = "BB-BONELT-HDMIN";
+			};
+
+		};
+									  
+		/* mapping between board names and dtb objects */
+		capemaps {
+			/* DVI cape */
+			cape@0 {
+				/* board-name = "BeagleBone DVI-D CAPE"; */
+				part-number = "BB-BONE-DVID-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-dvi-00A0.dtbo";
+				};
+				version@00A1 {
+					version = "00A1", "01";
+					dtbo = "cape-bone-dvi-00A1.dtbo";
+				};
+				version@00A2 {
+					version = "00A2", "A2";
+					dtbo = "cape-bone-dvi-00A2.dtbo";
+				};
+				version@00A3 {
+					version = "00A3";
+					dtbo = "cape-bone-dvi-00A2.dtbo";
+				};
+			};
+
+			/* beaglebone black emmc on board */
+			cape@1 {
+				/* board-name = "BeagleBone 2G eMMC1 CAPE"; */
+				part-number = "BB-BONE-EMMC-2G";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-2g-emmc1.dtbo";
+				};
+			};
+
+			/* geiger cape */
+			cape@2 {
+				part-number = "BB-BONE-GEIGER";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-geiger-00A0.dtbo";
+				};
+			};
+
+			/* LCD3 cape */
+			cape@3 {
+				part-number = "BB-BONE-LCD3-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-lcd3-00A0.dtbo";
+				};
+				version@00A2 {
+					version = "00A2";
+					dtbo = "cape-bone-lcd3-00A2.dtbo";
+				};
+			};
+
+			/* Weather cape */
+			cape@4 {
+				part-number = "BB-BONE-WTHR-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-weather-00A0.dtbo";
+				};
+			};
+
+			/* beaglebone black hdmi on board */
+			cape@5 {
+				part-number = "BB-BONELT-HDMI";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-boneblack-hdmi-00A0.dtbo";
+				};
+			};
+
+			/* nixie cape */
+			cape@6 {
+				part-number = "BB-BONE-NIXIE";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-nixie-00A0.dtbo";
+				};
+			};
+			cape@7 {
+				part-number = "BB-BONE-TFT-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-adafruit-lcd-00A0.dtbo";
+				};
+			};
+
+			cape@8 {
+				part-number = "BB-BONE-RTC-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-adafruit-rtc-00A0.dtbo";
+				};
+			};
+
+			cape@9 {
+				part-number = "BB-BONE-HEXY-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-hexy-00A0.dtbo";
+				};
+			};
+			/* mrf24j40 cape */
+			cape@10 {
+				part-number = "BB-BONE-MRF24J40";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-mrf24j40-00A0.dtbo";
+				};
+			};
+			/* expansion test */
+			cape@11 {
+				part-number = "BB-BONE-EXPTEST";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-exptest-00A0.dtbo";
+				};
+			};
+ 			cape@12 {
+				part-number = "BB-BONE-RS232-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "BB-BONE-RS232-00A0.dtbo";
+				};
+			};
+
+			/* beaglebone black hdmi on board (No audio) */
+			cape@13 {
+				part-number = "BB-BONELT-HDMIN";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-boneblack-hdmin-00A0.dtbo";
+				};
+			};
+
+		};
+	};
+
+	vmmcsd_fixed: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	tps: tps@24 {
+		reg = <0x24>;
+	};
+
+	baseboard_eeprom: baseboard_eeprom@50 {
+		compatible = "at,24c256";
+		reg = <0x50>;
+	};
+};
+
+&i2c2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+
+	clock-frequency = <100000>;
+
+	cape_eeprom0: cape_eeprom0@54 {
+		compatible = "at,24c256";
+		reg = <0x54>;
+	};
+
+	cape_eeprom1: cape_eeprom1@55 {
+		compatible = "at,24c256";
+		reg = <0x55>;
+	};
+
+	cape_eeprom2: cape_eeprom2@56 {
+		compatible = "at,24c256";
+		reg = <0x56>;
+	};
+
+	cape_eeprom3: cape_eeprom3@57 {
+		compatible = "at,24c256";
+		reg = <0x57>;
+	};
+};
+
+/include/ "tps65217.dtsi"
+
+&tps {
+	ti,pmic-shutdown-controller;
+
+	interrupt-parent = <&intc>;
+	interrupts = <7>;	/* NNMI */
+
+	regulators {
+		dcdc1_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		dcdc2_reg: regulator@1 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1325000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3_reg: regulator@2 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo1_reg: regulator@3 {
+			regulator-always-on;
+		};
+
+		ldo2_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		ldo3_reg: regulator@5 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		ldo4_reg: regulator@6 {
+			regulator-always-on;
+		};
+	};
+
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&ldo3_reg>;
+	ti,vcc-aux-disable-is-sleep;
+};
+
+&edma {
+	ti,edma-xbar-event-map = <32 12>,	/* gpevt2 -> 12 */
+				 <30 20>;	/* xdma_event_intr2 -> 20 */
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&usb_otg_hs {
+	interface_type = <1>;
+	power = <250>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
index 11b240c..9abc1f3 100644
--- a/arch/arm/boot/dts/am335x-bone.dts
+++ b/arch/arm/boot/dts/am335x-bone.dts
@@ -9,130 +9,4 @@
 
 /include/ "am33xx.dtsi"
 
-/ {
-	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";
-		};
-
-		i2c1: i2c@44e0b000 {
-			status = "okay";
-			clock-frequency = <400000>;
-
-			tps: tps@24 {
-				reg = <0x24>;
-			};
-
-		};
-	};
-
-	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"
-
-&tps {
-	regulators {
-		dcdc1_reg: regulator@0 {
-			regulator-always-on;
-		};
-
-		dcdc2_reg: regulator@1 {
-			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
-			regulator-name = "vdd_mpu";
-			regulator-min-microvolt = <925000>;
-			regulator-max-microvolt = <1325000>;
-			regulator-boot-on;
-			regulator-always-on;
-		};
-
-		dcdc3_reg: regulator@2 {
-			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
-			regulator-name = "vdd_core";
-			regulator-min-microvolt = <925000>;
-			regulator-max-microvolt = <1150000>;
-			regulator-boot-on;
-			regulator-always-on;
-		};
-
-		ldo1_reg: regulator@3 {
-			regulator-always-on;
-		};
-
-		ldo2_reg: regulator@4 {
-			regulator-always-on;
-		};
-
-		ldo3_reg: regulator@5 {
-			regulator-always-on;
-		};
-
-		ldo4_reg: regulator@6 {
-			regulator-always-on;
-		};
-	};
-};
-
-&cpsw_emac0 {
-	phy_id = <&davinci_mdio>, <0>;
-};
-
-&cpsw_emac1 {
-	phy_id = <&davinci_mdio>, <1>;
-};
+/include/ "am335x-bone-common.dtsi"
diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
new file mode 100644
index 0000000..a7eb55b
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-boneblack.dts
@@ -0,0 +1,69 @@
+/*
+ * 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/ "am33xx.dtsi"
+
+/include/ "am335x-bone-common.dtsi"
+
+&am33xx_pinmux {
+	rstctl_pins: pinmux_rstctl_pins {
+		pinctrl-single,pins = <
+			/* eMMC_RSTn */
+			0x50 0x17	/* gpmc_a4.gpio1_20, OUTPUT | MODE7 | PULLUP */
+		>;
+	};
+};
+
+&ldo3_reg {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-always-on;
+};
+
+&rstctl {
+	status = "okay";
+	compatible = "gpio-rctrl";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rstctl_pins>;
+
+	#reset-cells = <2>;
+
+	gpios = <&gpio2 20 0x00>;
+	gpio-names = "eMMC_RSTn";
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <8>;
+	ti,non-removable;
+	status = "disabled";
+
+	reset = <&rstctl 0 0>;
+	reset-names = "eMMC_RSTn-CONSUMER";
+};
+
+
+&cpu {
+	/*
+	 * 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 */
+		1000000	1350000
+		800000	1300000
+		600000  1112000
+		300000   969000
+	>;
+};
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index d649644..d83be11 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -26,7 +26,7 @@
 
 	am33xx_pinmux: pinmux@44e10800 {
 		pinctrl-names = "default";
-		pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0>;
+		pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &lcd_pins_s0>;
 
 		matrix_keypad_s0: matrix_keypad_s0 {
 			pinctrl-single,pins = <
@@ -44,6 +44,54 @@
 				0x154 0x27	/* spi0_d0.gpio0_3, INPUT | MODE7 */
 			>;
 		};
+
+		spi0_pins_s0: spi0_pins_s0 {
+			pinctrl-single,pins = <
+				0x150 0x30	/* spi0_sclk.spi0_sclk, INPUT_PULLUP | MODE0 */
+				0x154 0x30	/* spi0_d0.spi0_d0, INPUT_PULLUP | MODE0 */
+				0x158 0x10	/* spi0_d1.spi0_d1, OUTPUT_PULLUP | MODE0 */
+				0x15c 0x10	/* spi0_cs0.spi0_cs0, OUTPUT_PULLUP | MODE0 */
+			>;
+		};
+
+		lcd_pins_s0: lcd_pins_s0 {
+			pinctrl-single,pins = <
+				0x20 0x01	/* gpmc_ad8.lcd_data16, OUTPUT | MODE1 */
+				0x24 0x01	/* gpmc_ad9.lcd_data17, OUTPUT | MODE1 */
+				0x28 0x01	/* gpmc_ad10.lcd_data18, OUTPUT | MODE1 */
+				0x2c 0x01	/* gpmc_ad11.lcd_data19, OUTPUT | MODE1 */
+				0x30 0x01	/* gpmc_ad12.lcd_data20, OUTPUT | MODE1 */
+				0x34 0x01	/* gpmc_ad13.lcd_data21, OUTPUT | MODE1 */
+				0x38 0x01	/* gpmc_ad14.lcd_data22, OUTPUT | MODE1 */
+				0x3c 0x01	/* gpmc_ad15.lcd_data23, OUTPUT | MODE1 */
+				0xa0 0x00	/* lcd_data0.lcd_data0, OUTPUT | MODE0 */
+				0xa4 0x00	/* lcd_data1.lcd_data1, OUTPUT | MODE0 */
+				0xa8 0x00	/* lcd_data2.lcd_data2, OUTPUT | MODE0 */
+				0xac 0x00	/* lcd_data3.lcd_data3, OUTPUT | MODE0 */
+				0xb0 0x00	/* lcd_data4.lcd_data4, OUTPUT | MODE0 */
+				0xb4 0x00	/* lcd_data5.lcd_data5, OUTPUT | MODE0 */
+				0xb8 0x00	/* lcd_data6.lcd_data6, OUTPUT | MODE0 */
+				0xbc 0x00	/* lcd_data7.lcd_data7, OUTPUT | MODE0 */
+				0xc0 0x00	/* lcd_data8.lcd_data8, OUTPUT | MODE0 */
+				0xc4 0x00	/* lcd_data9.lcd_data9, OUTPUT | MODE0 */
+				0xc8 0x00	/* lcd_data10.lcd_data10, OUTPUT | MODE0 */
+				0xcc 0x00	/* lcd_data11.lcd_data11, OUTPUT | MODE0 */
+				0xd0 0x00	/* lcd_data12.lcd_data12, OUTPUT | MODE0 */
+				0xd4 0x00	/* lcd_data13.lcd_data13, OUTPUT | MODE0 */
+				0xd8 0x00	/* lcd_data14.lcd_data14, OUTPUT | MODE0 */
+				0xdc 0x00	/* lcd_data15.lcd_data15, OUTPUT | MODE0 */
+				0xe0 0x00	/* lcd_vsync.lcd_vsync, OUTPUT | MODE0 */
+				0xe4 0x00	/* lcd_hsync.lcd_hsync, OUTPUT | MODE0 */
+				0xe8 0x00	/* lcd_pclk.lcd_pclk, OUTPUT | MODE0 */
+				0xec 0x00	/* lcd_ac_bias_en.lcd_ac_bias_en, OUTPUT | MODE0 */
+			>;
+		};
+
+		ecap0_pins: backlight_pins {
+			pinctrl-single,pins = <
+				0x164 0x0	/* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
+			>;
+		};
 	};
 
 	ocp {
@@ -51,7 +99,7 @@
 			status = "okay";
 		};
 
-		i2c1: i2c@44e0b000 {
+		i2c0: i2c@44e0b000 {
 			status = "okay";
 			clock-frequency = <400000>;
 
@@ -60,7 +108,7 @@
 			};
 		};
 
-		i2c2: i2c@4802a000 {
+		i2c20: i2c@4802a000 {
 			status = "okay";
 			clock-frequency = <100000>;
 
@@ -102,6 +150,16 @@
 				reg = <0x48>;
 			};
 		};
+
+		epwmss0: epwmss@48300000 {
+			status = "okay";
+
+			ecap0: ecap@48300100 {
+				status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <&ecap0_pins>;
+			};
+		};
 	};
 
 	vbat: fixedregulator@0 {
@@ -158,6 +216,13 @@
 			gpio-key,wakeup;
 		};
 	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&ecap0 0 50000 0>;
+		brightness-levels = <0 51 53 56 62 75 101 152 255>;
+		default-brightness-level = <8>;
+	};
 };
 
 /include/ "tps65910.dtsi"
@@ -232,6 +297,8 @@
 		};
 
 		vmmc_reg: regulator@12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
 	};
@@ -244,3 +311,58 @@
 &cpsw_emac1 {
 	phy_id = <&davinci_mdio>, <1>;
 };
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmc_reg>;
+};
+
+&spi0 {
+	status = "okay";
+	spi-flash@0 {
+		compatible = "spansion,s25fl064k", "m25p80";
+		spi-max-frequency = <24000000>;
+		reg = <0>;
+	};
+};
+
+&tscadc {
+	tsc {
+		ti,wires = <4>;
+		ti,x-plate-resistance = <200>;
+		ti,steps-to-configure = <5>;
+		ti,wire-config = <0x00 0x11 0x22 0x33>;
+	};
+
+	adc {
+		ti,adc-channels = <4 5 6 7>;
+	};
+};
+
+&lcdc {
+	status = "okay";
+
+	display-timings {
+		800x480p62 {
+			clock-frequency = <30000000>;
+			hactive = <800>;
+			vactive = <480>;
+			hfront-porch = <39>;
+			hback-porch = <39>;
+			hsync-len = <47>;
+			vback-porch = <29>;
+			vfront-porch = <13>;
+			vsync-len = <2>;
+			hsync-active = <1>;
+			vsync-active = <1>;
+		};
+	};
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
index f5a6162..5aa07e7 100644
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -32,7 +32,7 @@
 
 	am33xx_pinmux: pinmux@44e10800 {
 		pinctrl-names = "default";
-		pinctrl-0 = <&user_leds_s0 &gpio_keys_s0>;
+		pinctrl-0 = <&user_leds_s0 &gpio_keys_s0 &lcd_pins_s0>;
 
 		user_leds_s0: user_leds_s0 {
 			pinctrl-single,pins = <
@@ -51,6 +51,45 @@
 				0x9c 0x27	/* gpmc_ben0_cle.gpio2_5, INPUT | MODE7 */
 			>;
 		};
+
+		lcd_pins_s0: lcd_pins_s0 {
+			pinctrl-single,pins = <
+				0x20 0x01	/* gpmc_ad8.lcd_data16, OUTPUT | MODE1 */
+				0x24 0x01	/* gpmc_ad9.lcd_data17, OUTPUT | MODE1 */
+				0x28 0x01	/* gpmc_ad10.lcd_data18, OUTPUT | MODE1 */
+				0x2c 0x01	/* gpmc_ad11.lcd_data19, OUTPUT | MODE1 */
+				0x30 0x01	/* gpmc_ad12.lcd_data20, OUTPUT | MODE1 */
+				0x34 0x01	/* gpmc_ad13.lcd_data21, OUTPUT | MODE1 */
+				0x38 0x01	/* gpmc_ad14.lcd_data22, OUTPUT | MODE1 */
+				0x3c 0x01	/* gpmc_ad15.lcd_data23, OUTPUT | MODE1 */
+				0xa0 0x00	/* lcd_data0.lcd_data0, OUTPUT | MODE0 */
+				0xa4 0x00	/* lcd_data1.lcd_data1, OUTPUT | MODE0 */
+				0xa8 0x00	/* lcd_data2.lcd_data2, OUTPUT | MODE0 */
+				0xac 0x00	/* lcd_data3.lcd_data3, OUTPUT | MODE0 */
+				0xb0 0x00	/* lcd_data4.lcd_data4, OUTPUT | MODE0 */
+				0xb4 0x00	/* lcd_data5.lcd_data5, OUTPUT | MODE0 */
+				0xb8 0x00	/* lcd_data6.lcd_data6, OUTPUT | MODE0 */
+				0xbc 0x00	/* lcd_data7.lcd_data7, OUTPUT | MODE0 */
+				0xc0 0x00	/* lcd_data8.lcd_data8, OUTPUT | MODE0 */
+				0xc4 0x00	/* lcd_data9.lcd_data9, OUTPUT | MODE0 */
+				0xc8 0x00	/* lcd_data10.lcd_data10, OUTPUT | MODE0 */
+				0xcc 0x00	/* lcd_data11.lcd_data11, OUTPUT | MODE0 */
+				0xd0 0x00	/* lcd_data12.lcd_data12, OUTPUT | MODE0 */
+				0xd4 0x00	/* lcd_data13.lcd_data13, OUTPUT | MODE0 */
+				0xd8 0x00	/* lcd_data14.lcd_data14, OUTPUT | MODE0 */
+				0xdc 0x00	/* lcd_data15.lcd_data15, OUTPUT | MODE0 */
+				0xe0 0x00	/* lcd_vsync.lcd_vsync, OUTPUT | MODE0 */
+				0xe4 0x00	/* lcd_hsync.lcd_hsync, OUTPUT | MODE0 */
+				0xe8 0x00	/* lcd_pclk.lcd_pclk, OUTPUT | MODE0 */
+				0xec 0x00	/* lcd_ac_bias_en.lcd_ac_bias_en, OUTPUT | MODE0 */
+			>;
+		};
+
+		ecap2_pins: backlight_pins {
+			pinctrl-single,pins = <
+				0x19c 0x4	/* mcasp0_ahclkr.ecap2_in_pwm2_out MODE4 */
+			>;
+		};
 	};
 
 	ocp {
@@ -58,7 +97,7 @@
 			status = "okay";
 		};
 
-		i2c1: i2c@44e0b000 {
+		i2c10: i2c@44e0b000 {
 			status = "okay";
 			clock-frequency = <400000>;
 
@@ -94,6 +133,16 @@
 				st,max-limit-z = <750>;
 			};
 		};
+
+		epwmss2: epwmss@48304000 {
+			status = "okay";
+
+			ecap2: ecap@48304100 {
+				status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <&ecap2_pins>;
+			};
+		};
 	};
 
 	vbat: fixedregulator@0 {
@@ -170,6 +219,13 @@
 			gpios = <&gpio3 5 0>;
 		};
 	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&ecap2 0 50000 1>;
+		brightness-levels = <0 58 61 66 75 90 125 170 255>;
+		default-brightness-level = <8>;
+	};
 };
 
 /include/ "tps65910.dtsi"
@@ -244,7 +300,42 @@
 		};
 
 		vmmc_reg: regulator@12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
 	};
 };
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmc_reg>;
+};
+
+&lcdc {
+	status = "okay";
+
+	display-timings {
+		480x272p57 {
+			clock-frequency = <9000000>;
+			hactive = <480>;
+			vactive = <272>;
+			hfront-porch = <8>;
+			hback-porch = <43>;
+			hsync-len = <4>;
+			vback-porch = <12>;
+			vfront-porch = <4>;
+			vsync-len = <10>;
+			hsync-active = <1>;
+			vsync-active = <1>;
+		};
+	};
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/am335x-tester.dts b/arch/arm/boot/dts/am335x-tester.dts
new file mode 100644
index 0000000..c6ac8bf
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-tester.dts
@@ -0,0 +1,483 @@
+/*
+ * 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/ "am33xx.dtsi"
+
+/ {
+	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 = <&userleds_pins>;
+
+		spi1_pins_s0: spi1_pins_s0 {
+			pinctrl-single,pins = <
+				0x190 0x33	/* mcasp0_aclkx.spi1_sclk, INPUT_PULLUP | MODE3 */
+				0x194 0x33	/* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
+				0x198 0x13	/* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
+				0x19c 0x13	/* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+			>;
+		};
+		userled_pins: pinmux_userled_pins {
+			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 */
+			>;
+		};
+		i2c0_pins: pinmux_i2c0_pins {
+			pinctrl-single,pins = <
+				0x188 0x70 	/* i2c0_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */
+				0x18c 0x70	/* i2c0_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */
+			>;
+		};
+		// i2c2_pins: pinmux_i2c2_pins {
+		//	pinctrl-single,pins = <
+		//		0x178 0x73 	/* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+		//		0x17c 0x73	/* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+		//	>;
+		// };
+	};
+
+	ocp: ocp {
+		uart1: serial@44e09000 {
+			status = "okay";
+		};
+
+		gpio-leds {
+			compatible = "gpio-leds";
+			pinctrl-names = "default";
+			pinctrl-0 = <&userled_pins>;
+
+			led0 {
+				label = "beaglebone:green:usr0";
+				gpios = <&gpio2 21 0>;
+				linux,default-trigger = "heartbeat";
+				default-state = "off";
+			};
+
+			led1 {
+				label = "beaglebone:green:usr1";
+				gpios = <&gpio2 22 0>;
+				linux,default-trigger = "mmc0";
+				default-state = "off";
+			};
+
+			led2 {
+				label = "beaglebone:green:usr2";
+				gpios = <&gpio2 23 0>;
+				linux,default-trigger = "cpu0";
+				default-state = "off";
+			};
+
+			led3 {
+				label = "beaglebone:green:usr3";
+				gpios = <&gpio2 24 0>;
+				default-state = "off";
+				linux,default-trigger = "mmc1";
+			};
+		};
+
+		rtc@44e3e000 {
+			ti,system-power-controller;
+		};
+	};
+
+	bone_capemgr {
+		compatible = "ti,bone-capemgr";
+		status = "okay";
+
+		eeprom = <&baseboard_eeprom>;
+
+		baseboardmaps {
+			baseboard_beaglebone: board@0 {
+				board-name = "A335BONE";
+				compatible-name = "ti,beaglebone";
+			};
+
+			baseboard_beaglebone_black: board@1 {
+				board-name = "A335BNLT";
+				compatible-name = "ti,beaglebone-black";
+			};
+		};
+
+		slots {
+			// slot@0 {
+			//	eeprom = <&cape_eeprom0>;
+			// };
+			//
+			// slot@1 {
+			//	eeprom = <&cape_eeprom1>;
+			// };
+			//
+			// slot@2 {
+			//	eeprom = <&cape_eeprom2>;
+			// };
+			//
+			// slot@3 {
+			//	eeprom = <&cape_eeprom3>;
+			// };
+
+			/* Beaglebone black has it soldered on */
+			 slot@4 {
+			 	ti,cape-override;
+			 	compatible = "ti,beaglebone-black";
+			 	board-name = "Bone-LT-eMMC-2G";
+			 	version = "00A0";
+			 	manufacturer = "Texas Instruments";
+			 	part-number = "BB-BONE-EMMC-2G";
+			 };
+
+			/* geiger cape version A0 without an EEPROM */
+			slot@5 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "Bone-Geiger";
+				version = "00A0";
+				manufacturer = "Geiger Inc.";
+				part-number = "BB-BONE-GEIGER";
+			};
+
+			/* Beaglebone black has it soldered on */
+			slot@6 {
+				ti,cape-override;
+				compatible = "ti,beaglebone-black";
+				board-name = "Bone-Black-HDMI";
+				version = "00A0";
+				manufacturer = "Texas Instruments";
+				part-number = "BB-BONELT-HDMI";
+			};
+
+			/* Nixie cape version A0 without an EEPROM */
+			slot@7 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "Bone-Nixie";
+				version = "00A0";
+				manufacturer = "Ranostay Industries";
+				part-number = "BB-BONE-NIXIE";
+			};
+
+			/* adafruit 1.8" TFT prototype cape */
+			slot@8 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "Bone-TFT";
+				version = "00A0";
+				manufacturer = "Adafruit";
+				part-number = "BB-BONE-TFT-01";
+			};
+
+			/* adafruit RTC DS1307 prototype cape */
+			slot@9 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "Bone-RTC";
+				version = "00A0";
+				manufacturer = "Adafruit";
+				part-number = "BB-BONE-RTC-01";
+			};
+
+			slot@10 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "Bone-Hexy";
+				version = "00A0";
+				manufacturer = "Koen Kooi";
+				part-number = "BB-BONE-HEXY-01";
+			};
+			/* MRF24J40 Cape Override */
+			slot@11 {
+				ti,cape-override;
+				compatible = "kernel-command-line", "runtime";
+				board-name = "Bone-MRF24J40";
+				version = "00A0";
+				manufacturer = "Signal 11 Software";
+				part-number = "BB-BONE-MRF24J40";
+			};
+		};
+
+		/* mapping between board names and dtb objects */
+		capemaps {
+			/* DVI cape */
+			cape@0 {
+				/* board-name = "BeagleBone DVI-D CAPE"; */
+				part-number = "BB-BONE-DVID-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-dvi-00A0.dtbo";
+				};
+				version@00A1 {
+					version = "00A1", "01";
+					dtbo = "cape-bone-dvi-00A1.dtbo";
+				};
+				version@00A2 {
+					version = "00A2", "A2";
+					dtbo = "cape-bone-dvi-00A2.dtbo";
+				};
+				version@00A3 {
+					version = "00A3";
+					dtbo = "cape-bone-dvi-00A2.dtbo";
+				};
+			};
+
+			/* tester */
+			cape@100 {
+				part-number = "BB-BONE-TESTER";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-tester-00A0.dtbo";
+				};
+			};
+
+			/* beaglebone black emmc on board */
+			cape@1 {
+				/* board-name = "BeagleBone 2G eMMC1 CAPE"; */
+				part-number = "BB-BONE-EMMC-2G";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-2g-emmc1.dtbo";
+				};
+			};
+
+			/* geiger cape */
+			cape@2 {
+				part-number = "BB-BONE-GEIGER";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-geiger-00A0.dtbo";
+				};
+			};
+
+			/* LCD3 cape */
+			cape@3 {
+				part-number = "BB-BONE-LCD3-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-lcd3-00A0.dtbo";
+				};
+				version@00A2 {
+					version = "00A2";
+					dtbo = "cape-bone-lcd3-00A2.dtbo";
+				};
+			};
+
+			/* Weather cape */
+			cape@4 {
+				part-number = "BB-BONE-WTHR-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-weather-00A0.dtbo";
+				};
+			};
+
+			/* beaglebone black hdmi on board */
+			cape@5 {
+				part-number = "BB-BONELT-HDMI";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-boneblack-hdmi-00A0.dtbo";
+				};
+			};
+
+			/* nixie cape */
+			cape@6 {
+				part-number = "BB-BONE-NIXIE";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-nixie-00A0.dtbo";
+				};
+			};
+			cape@7 {
+				part-number = "BB-BONE-TFT-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-adafruit-lcd-00A0.dtbo";
+				};
+			};
+
+			cape@8 {
+				part-number = "BB-BONE-RTC-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-adafruit-rtc-00A0.dtbo";
+				};
+			};
+
+			cape@9 {
+				part-number = "BB-BONE-HEXY-01";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-hexy-00A0.dtbo";
+				};
+			};
+			/* mrf24j40 cape */
+			cape@10 {
+				part-number = "BB-BONE-MRF24J40";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-mrf24j40-00A0.dtbo";
+				};
+			};
+			/* expansion test */
+			cape@11 {
+				part-number = "BB-BONE-EXPTEST";
+				version@00A0 {
+					version = "00A0";
+					dtbo = "cape-bone-exptest-00A0.dtbo";
+				};
+			};
+		};
+	};
+
+	vmmcsd_fixed: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	tps: tps@24 {
+		reg = <0x24>;
+	};
+
+	baseboard_eeprom: baseboard_eeprom@50 {
+		compatible = "at,24c256";
+		reg = <0x50>;
+	};
+};
+
+// &i2c2 {
+//	status = "okay";
+//	pinctrl-names = "default";
+//	pinctrl-0 = <&i2c2_pins>;
+//
+//	clock-frequency = <100000>;
+//
+//	cape_eeprom0: cape_eeprom0@54 {
+//		compatible = "at,24c256";
+//		reg = <0x54>;
+//	};
+//
+//	cape_eeprom1: cape_eeprom1@55 {
+//		compatible = "at,24c256";
+//		reg = <0x55>;
+//	};
+//
+//	cape_eeprom2: cape_eeprom2@56 {
+//		compatible = "at,24c256";
+//		reg = <0x56>;
+//	};
+//
+//	cape_eeprom3: cape_eeprom3@57 {
+//		compatible = "at,24c256";
+//		reg = <0x57>;
+//	};
+// };
+
+/include/ "tps65217.dtsi"
+
+&tps {
+	ti,pmic-shutdown-controller;
+
+	regulators {
+		dcdc1_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		dcdc2_reg: regulator@1 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1325000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3_reg: regulator@2 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo1_reg: regulator@3 {
+			regulator-always-on;
+		};
+
+		ldo2_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		ldo3_reg: regulator@5 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		ldo4_reg: regulator@6 {
+			regulator-always-on;
+		};
+	};
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&ldo3_reg>;
+	ti,vcc-aux-disable-is-sleep;
+};
+
+&edma {
+	ti,edma-xbar-event-map = <32 12>;
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&usb_otg_hs {
+	interface_type = <1>;
+	power = <250>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index c2f14e8..eb0d2d4 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -24,7 +24,7 @@
 	};
 
 	cpus {
-		cpu@0 {
+		cpu: cpu@0 {
 			compatible = "arm,cortex-a8";
 
 			/*
@@ -34,6 +34,10 @@
 			 */
 			operating-points = <
 				/* kHz    uV */
+				/* ES 2.0 Nitro and Turbo OPPs"
+				1000000	1350000
+				800000	1300000
+				*/
 				720000  1285000
 				600000  1225000
 				500000  1125000
@@ -87,6 +91,26 @@
 			reg = <0x48200000 0x1000>;
 		};
 
+		edma: edma@49000000 {
+			compatible = "ti,edma3";
+			ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
+			reg =	<0x49000000 0x10000>,
+				<0x44e10f90 0x40>;
+			interrupt-parent = <&intc>;
+			interrupts = <12 13 14>;
+			#dma-cells = <1>;
+			dma-channels = <64>;
+			ti,edma-regions = <4>;
+			ti,edma-slots = <256>;
+			ti,edma-queue-tc-map = <0 0
+						1 1
+						2 2>;
+			ti,edma-queue-priority-map = <0 0
+						      1 1
+						      2 2>;
+			ti,edma-default-queue = <1>;
+		};
+
 		gpio1: gpio@44e07000 {
 			compatible = "ti,omap4-gpio";
 			ti,hwmods = "gpio1";
@@ -131,6 +155,11 @@
 			interrupts = <62>;
 		};
 
+		/* reset controller comes first (even if disabled) */
+		rstctl: rstctl@0 {
+			status = "disabled";
+		};
+
 		uart1: serial@44e09000 {
 			compatible = "ti,omap3-uart";
 			ti,hwmods = "uart1";
@@ -185,36 +214,67 @@
 			status = "disabled";
 		};
 
-		i2c1: i2c@44e0b000 {
+		i2c0: i2c@44e0b000 {
 			compatible = "ti,omap4-i2c";
 			#address-cells = <1>;
 			#size-cells = <0>;
-			ti,hwmods = "i2c1";
+			ti,hwmods = "i2c1";	/* TODO: Fix hwmod */
 			reg = <0x44e0b000 0x1000>;
 			interrupts = <70>;
 			status = "disabled";
 		};
 
-		i2c2: i2c@4802a000 {
+		i2c1: i2c@4802a000 {
 			compatible = "ti,omap4-i2c";
 			#address-cells = <1>;
 			#size-cells = <0>;
-			ti,hwmods = "i2c2";
+			ti,hwmods = "i2c2";	/* TODO: Fix hwmod */
 			reg = <0x4802a000 0x1000>;
 			interrupts = <71>;
 			status = "disabled";
 		};
 
-		i2c3: i2c@4819c000 {
+		i2c2: i2c@4819c000 {
 			compatible = "ti,omap4-i2c";
 			#address-cells = <1>;
 			#size-cells = <0>;
-			ti,hwmods = "i2c3";
+			ti,hwmods = "i2c3";	/* TODO: Fix hwmod */
 			reg = <0x4819c000 0x1000>;
 			interrupts = <30>;
 			status = "disabled";
 		};
 
+		mmc1: mmc@48060000 {
+			compatible = "ti,omap3-hsmmc";
+			ti,hwmods = "mmc1";
+			ti,dual-volt;
+			ti,needs-special-reset;
+			ti,needs-special-hs-handling;
+			dmas = <&edma 24
+				&edma 25>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		mmc2: mmc@481d8000 {
+			compatible = "ti,omap3-hsmmc";
+			ti,hwmods = "mmc2";
+			ti,needs-special-reset;
+			ti,needs-special-hs-handling;
+			dmas = <&edma 2
+				&edma 3>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		mmc3: mmc@47810000 {
+			compatible = "ti,omap3-hsmmc";
+			ti,hwmods = "mmc3";
+			ti,needs-special-reset;
+			ti,needs-special-hs-handling;
+			status = "disabled";
+		};
+
 		wdt2: wdt@44e35000 {
 			compatible = "ti,omap3-wdt";
 			ti,hwmods = "wd_timer2";
@@ -292,6 +352,17 @@
 			ti,timer-pwm;
 		};
 
+		pruss: pruss@4a300000 {
+			compatible = "ti,pruss-v2";
+			ti,hwmods = "pruss";
+			ti,deassert-hard-reset = "pruss", "pruss";
+			reg = <0x4a300000 0x080000>;
+			ti,pintc-offset = <0x20000>;
+			interrupt-parent = <&intc>;
+			status = "disabled";
+			interrupts = <20 21 22 23 24 25 26 27>;
+		};
+
 		rtc@44e3e000 {
 			compatible = "ti,da830-rtc";
 			reg = <0x44e3e000 0x1000>;
@@ -308,6 +379,11 @@
 			interrupt = <65>;
 			ti,spi-num-cs = <2>;
 			ti,hwmods = "spi0";
+			dmas = <&edma 16
+				&edma 17
+				&edma 18
+				&edma 19>;
+			dma-names = "tx0", "rx0", "tx1", "rx1";
 			status = "disabled";
 		};
 
@@ -319,10 +395,37 @@
 			interrupt = <125>;
 			ti,spi-num-cs = <2>;
 			ti,hwmods = "spi1";
+			dmas = <&edma 42
+				&edma 43
+				&edma 44
+				&edma 45>;
+			dma-names = "tx0", "rx0", "tx1", "rx1";
 			status = "disabled";
+
 		};
 
-		usb@47400000 {
+		gpmc: gpmc@50000000 {
+			compatible = "ti,am3352-gpmc";
+			ti,hwmods = "gpmc";
+			reg = <0x50000000 0x01000000>;
+			interrupts = <100>;
+			gpmc,num-cs = <7>;
+			gpmc,num-waitpins = <2>;
+			#address-cells = <2>;
+			#size-cells = <1>;
+
+			status = "disabled";
+		};
+
+		nop-phy@0 {
+			compatible = "nop-xceiv-usb";
+		};
+
+		nop-phy@1 {
+			compatible = "nop-xceiv-usb";
+		};
+
+		usb_otg_hs: usb@47400000 {
 			compatible = "ti,musb-am33xx";
 			reg = <0x47400000 0x1000	/* usbss */
 			       0x47401000 0x800		/* musb instance 0 */
@@ -334,9 +437,10 @@
 			num-eps = <16>;
 			ram-bits = <12>;
 			port0-mode = <3>;
-			port1-mode = <3>;
+			port1-mode = <1>;
 			power = <250>;
 			ti,hwmods = "usb_otg_hs";
+			status = "disabled";
 		};
 
 		mac: ethernet@4a100000 {
@@ -365,6 +469,7 @@
 			 */
 			interrupts = <40 41 42 43>;
 			ranges;
+			disable-napi;
 
 			davinci_mdio: mdio@4a101000 {
 				compatible = "ti,davinci_mdio";
@@ -385,5 +490,164 @@
 				mac-address = [ 00 00 00 00 00 00 ];
 			};
 		};
+
+		tscadc: tscadc@44e0d000 {
+			compatible = "ti,ti-tscadc";
+			reg = <0x44e0d000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <16>;
+			ti,hwmods = "adc_tsc";
+			status = "disabled";
+		};
+
+		lcdc: lcdc@4830e000 {
+			compatible = "ti,am3352-lcdc", "ti,da830-lcdc";
+			reg = <0x4830e000 0x1000>;
+			interrupts = <36>;
+			status = "disabled";
+			ti,hwmods = "lcdc";
+		};
+
+		epwmss0: epwmss@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 */
+
+			ecap0: ecap@48300100 {
+				compatible = "ti,am33xx-ecap";
+				#pwm-cells = <3>;
+				reg = <0x48300100 0x80>;
+				ti,hwmods = "ecap0";
+				status = "disabled";
+			};
+
+			ehrpwm0: ehrpwm@48300200 {
+				compatible = "ti,am33xx-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48300200 0x80>;
+				ti,hwmods = "ehrpwm0";
+				status = "disabled";
+			};
+		};
+
+		epwmss1: epwmss@48302000 {
+			compatible = "ti,am33xx-pwmss";
+			reg = <0x48302000 0x10>;
+			ti,hwmods = "epwmss1";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+			ranges = <0x48302100 0x48302100 0x80   /* ECAP */
+				  0x48302180 0x48302180 0x80   /* EQEP */
+				  0x48302200 0x48302200 0x80>; /* EHRPWM */
+
+			ecap1: ecap@48302100 {
+				compatible = "ti,am33xx-ecap";
+				#pwm-cells = <3>;
+				reg = <0x48302100 0x80>;
+				ti,hwmods = "ecap1";
+				status = "disabled";
+			};
+
+			ehrpwm1: ehrpwm@48302200 {
+				compatible = "ti,am33xx-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48302200 0x80>;
+				ti,hwmods = "ehrpwm1";
+				status = "disabled";
+			};
+		};
+
+		epwmss2: epwmss@48304000 {
+			compatible = "ti,am33xx-pwmss";
+			reg = <0x48304000 0x10>;
+			ti,hwmods = "epwmss2";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+			ranges = <0x48304100 0x48304100 0x80   /* ECAP */
+				  0x48304180 0x48304180 0x80   /* EQEP */
+				  0x48304200 0x48304200 0x80>; /* EHRPWM */
+
+			ecap2: ecap@48304100 {
+				compatible = "ti,am33xx-ecap";
+				#pwm-cells = <3>;
+				reg = <0x48304100 0x80>;
+				ti,hwmods = "ecap2";
+				status = "disabled";
+			};
+
+			ehrpwm2: ehrpwm@48304200 {
+				compatible = "ti,am33xx-ehrpwm";
+				#pwm-cells = <3>;
+				reg = <0x48304200 0x80>;
+				ti,hwmods = "ehrpwm2";
+				status = "disabled";
+			};
+		};
+
+		sham: sham@53100000 {
+			compatible = "ti,omap4-sham";
+			ti,hwmods = "sham";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x53100000 0x200>;
+			interrupt-parent = <&intc>;
+			interrupts = <109>;
+			dmas = <&edma 36>;
+			dma-names = "rx";
+		};
+
+		aes: aes@53500000 {
+			compatible = "ti,omap4-aes";
+			ti,hwmods = "aes";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x53500000 0xa0>;
+			interrupt-parent = <&intc>;
+			interrupts = <102>;
+			dmas = <&edma 6
+				&edma 5>;
+			dma-names = "tx", "rx";
+		};
+
+		mcasp0: mcasp@48038000 {
+			compatible = "ti,omap2-mcasp-audio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "mcasp0";
+			reg = <0x48038000 0x2000>;
+			interrupts = <80 81>;
+			status = "disabled";
+			asp-chan-q = <2>;	/* EVENTQ_2 */
+			tx-dma-offset = <0x46000000>;
+			rx-dma-offset = <0x46000000>;
+			dmas = <&edma 8
+				&edma 9>;
+			dma-names = "tx", "rx";
+		};
+
+		mcasp1: mcasp@4803C000 {
+			compatible = "ti,omap2-mcasp-audio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "mcasp1";
+			reg = <0x4803C000 0x2000>;
+			interrupts = <82 83>;
+			status = "disabled";
+			asp-chan-q = <2>;	/* EVENTQ_2 */
+			tx-dma-offset = <0x46400000>;
+			rx-dma-offset = <0x46400000>;
+			dmas = <&edma 10
+				&edma 11>;
+			dma-names = "tx", "rx";
+		};
+
 	};
 };
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 45ceeb0..9e32d0d 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -40,3 +40,6 @@ config SHARP_PARAM
 
 config SHARP_SCOOP
 	bool
+
+config TI_PRIV_EDMA
+	bool
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index e8a4e58..d09a39b 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o
 obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
 obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
 obj-$(CONFIG_ARM_TIMER_SP804)	+= timer-sp.o
+obj-$(CONFIG_TI_PRIV_EDMA)	+= edma.o
diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
new file mode 100644
index 0000000..7654324
--- /dev/null
+++ b/arch/arm/common/edma.c
@@ -0,0 +1,1844 @@
+/*
+ * EDMA3 support for DaVinci
+ *
+ * Copyright (C) 2006-2009 Texas 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/edma.h>
+#include <linux/err.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_dma.h>
+#include <linux/of_irq.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/platform_data/edma.h>
+
+/* Offsets matching "struct edmacc_param" */
+#define PARM_OPT		0x00
+#define PARM_SRC		0x04
+#define PARM_A_B_CNT		0x08
+#define PARM_DST		0x0c
+#define PARM_SRC_DST_BIDX	0x10
+#define PARM_LINK_BCNTRLD	0x14
+#define PARM_SRC_DST_CIDX	0x18
+#define PARM_CCNT		0x1c
+
+#define PARM_SIZE		0x20
+
+/* Offsets for EDMA CC global channel registers and their shadows */
+#define SH_ER		0x00	/* 64 bits */
+#define SH_ECR		0x08	/* 64 bits */
+#define SH_ESR		0x10	/* 64 bits */
+#define SH_CER		0x18	/* 64 bits */
+#define SH_EER		0x20	/* 64 bits */
+#define SH_EECR		0x28	/* 64 bits */
+#define SH_EESR		0x30	/* 64 bits */
+#define SH_SER		0x38	/* 64 bits */
+#define SH_SECR		0x40	/* 64 bits */
+#define SH_IER		0x50	/* 64 bits */
+#define SH_IECR		0x58	/* 64 bits */
+#define SH_IESR		0x60	/* 64 bits */
+#define SH_IPR		0x68	/* 64 bits */
+#define SH_ICR		0x70	/* 64 bits */
+#define SH_IEVAL	0x78
+#define SH_QER		0x80
+#define SH_QEER		0x84
+#define SH_QEECR	0x88
+#define SH_QEESR	0x8c
+#define SH_QSER		0x90
+#define SH_QSECR	0x94
+#define SH_SIZE		0x200
+
+/* Offsets for EDMA CC global registers */
+#define EDMA_REV	0x0000
+#define EDMA_CCCFG	0x0004
+#define EDMA_QCHMAP	0x0200	/* 8 registers */
+#define EDMA_DMAQNUM	0x0240	/* 8 registers (4 on OMAP-L1xx) */
+#define EDMA_QDMAQNUM	0x0260
+#define EDMA_QUETCMAP	0x0280
+#define EDMA_QUEPRI	0x0284
+#define EDMA_EMR	0x0300	/* 64 bits */
+#define EDMA_EMCR	0x0308	/* 64 bits */
+#define EDMA_QEMR	0x0310
+#define EDMA_QEMCR	0x0314
+#define EDMA_CCERR	0x0318
+#define EDMA_CCERRCLR	0x031c
+#define EDMA_EEVAL	0x0320
+#define EDMA_DRAE	0x0340	/* 4 x 64 bits*/
+#define EDMA_QRAE	0x0380	/* 4 registers */
+#define EDMA_QUEEVTENTRY	0x0400	/* 2 x 16 registers */
+#define EDMA_QSTAT	0x0600	/* 2 registers */
+#define EDMA_QWMTHRA	0x0620
+#define EDMA_QWMTHRB	0x0624
+#define EDMA_CCSTAT	0x0640
+
+#define EDMA_M		0x1000	/* global channel registers */
+#define EDMA_ECR	0x1008
+#define EDMA_ECRH	0x100C
+#define EDMA_SHADOW0	0x2000	/* 4 regions shadowing global channels */
+#define EDMA_PARM	0x4000	/* 128 param entries */
+
+#define PARM_OFFSET(param_no)	(EDMA_PARM + ((param_no) << 5))
+
+#define EDMA_DCHMAP	0x0100  /* 64 registers */
+#define CHMAP_EXIST	BIT(24)
+
+#define EDMA_MAX_DMACH           64
+#define EDMA_MAX_PARAMENTRY     512
+
+/*****************************************************************************/
+
+static void __iomem *edmacc_regs_base[EDMA_MAX_CC];
+
+static inline unsigned int edma_read(unsigned ctlr, int offset)
+{
+	return (unsigned int)__raw_readl(edmacc_regs_base[ctlr] + offset);
+}
+
+static inline void edma_write(unsigned ctlr, int offset, int val)
+{
+	__raw_writel(val, edmacc_regs_base[ctlr] + offset);
+}
+static inline void edma_modify(unsigned ctlr, int offset, unsigned and,
+		unsigned or)
+{
+	unsigned val = edma_read(ctlr, offset);
+	val &= and;
+	val |= or;
+	edma_write(ctlr, offset, val);
+}
+static inline void edma_and(unsigned ctlr, int offset, unsigned and)
+{
+	unsigned val = edma_read(ctlr, offset);
+	val &= and;
+	edma_write(ctlr, offset, val);
+}
+static inline void edma_or(unsigned ctlr, int offset, unsigned or)
+{
+	unsigned val = edma_read(ctlr, offset);
+	val |= or;
+	edma_write(ctlr, offset, val);
+}
+static inline unsigned int edma_read_array(unsigned ctlr, int offset, int i)
+{
+	return edma_read(ctlr, offset + (i << 2));
+}
+static inline void edma_write_array(unsigned ctlr, int offset, int i,
+		unsigned val)
+{
+	edma_write(ctlr, offset + (i << 2), val);
+}
+static inline void edma_modify_array(unsigned ctlr, int offset, int i,
+		unsigned and, unsigned or)
+{
+	edma_modify(ctlr, offset + (i << 2), and, or);
+}
+static inline void edma_or_array(unsigned ctlr, int offset, int i, unsigned or)
+{
+	edma_or(ctlr, offset + (i << 2), or);
+}
+static inline void edma_or_array2(unsigned ctlr, int offset, int i, int j,
+		unsigned or)
+{
+	edma_or(ctlr, offset + ((i*2 + j) << 2), or);
+}
+static inline void edma_write_array2(unsigned ctlr, int offset, int i, int j,
+		unsigned val)
+{
+	edma_write(ctlr, offset + ((i*2 + j) << 2), val);
+}
+static inline unsigned int edma_shadow0_read(unsigned ctlr, int offset)
+{
+	return edma_read(ctlr, EDMA_SHADOW0 + offset);
+}
+static inline unsigned int edma_shadow0_read_array(unsigned ctlr, int offset,
+		int i)
+{
+	return edma_read(ctlr, EDMA_SHADOW0 + offset + (i << 2));
+}
+static inline void edma_shadow0_write(unsigned ctlr, int offset, unsigned val)
+{
+	edma_write(ctlr, EDMA_SHADOW0 + offset, val);
+}
+static inline void edma_shadow0_write_array(unsigned ctlr, int offset, int i,
+		unsigned val)
+{
+	edma_write(ctlr, EDMA_SHADOW0 + offset + (i << 2), val);
+}
+static inline unsigned int edma_parm_read(unsigned ctlr, int offset,
+		int param_no)
+{
+	return edma_read(ctlr, EDMA_PARM + offset + (param_no << 5));
+}
+static inline void edma_parm_write(unsigned ctlr, int offset, int param_no,
+		unsigned val)
+{
+	edma_write(ctlr, EDMA_PARM + offset + (param_no << 5), val);
+}
+static inline void edma_parm_modify(unsigned ctlr, int offset, int param_no,
+		unsigned and, unsigned or)
+{
+	edma_modify(ctlr, EDMA_PARM + offset + (param_no << 5), and, or);
+}
+static inline void edma_parm_and(unsigned ctlr, int offset, int param_no,
+		unsigned and)
+{
+	edma_and(ctlr, EDMA_PARM + offset + (param_no << 5), and);
+}
+static inline void edma_parm_or(unsigned ctlr, int offset, int param_no,
+		unsigned or)
+{
+	edma_or(ctlr, EDMA_PARM + offset + (param_no << 5), or);
+}
+
+static inline void set_bits(int offset, int len, unsigned long *p)
+{
+	for (; len > 0; len--)
+		set_bit(offset + (len - 1), p);
+}
+
+static inline void clear_bits(int offset, int len, unsigned long *p)
+{
+	for (; len > 0; len--)
+		clear_bit(offset + (len - 1), p);
+}
+
+/*****************************************************************************/
+
+/* actual number of DMA channels and slots on this silicon */
+struct edma {
+	/* how many dma resources of each type */
+	unsigned	num_channels;
+	unsigned	num_region;
+	unsigned	num_slots;
+	unsigned	num_tc;
+	unsigned	num_cc;
+	enum dma_event_q 	default_queue;
+
+	/* list of channels with no even trigger; terminated by "-1" */
+	const s8	*noevent;
+
+	/* The edma_inuse bit for each PaRAM slot is clear unless the
+	 * channel is in use ... by ARM or DSP, for QDMA, or whatever.
+	 */
+	DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
+
+	/* The edma_unused bit for each channel is clear unless
+	 * it is not being used on this platform. It uses a bit
+	 * of SOC-specific initialization code.
+	 */
+	DECLARE_BITMAP(edma_unused, EDMA_MAX_DMACH);
+
+	unsigned	irq_res_start;
+	unsigned	irq_res_end;
+
+	struct dma_interrupt_data {
+		void (*callback)(unsigned channel, unsigned short ch_status,
+				void *data);
+		void *data;
+	} intr_data[EDMA_MAX_DMACH];
+};
+
+static struct edma *edma_cc[EDMA_MAX_CC];
+static int arch_num_cc;
+
+/* dummy param set used to (re)initialize parameter RAM slots */
+static const struct edmacc_param dummy_paramset = {
+	.link_bcntrld = 0xffff,
+	.ccnt = 1,
+};
+
+/*****************************************************************************/
+
+static void map_dmach_queue(unsigned ctlr, unsigned ch_no,
+		enum dma_event_q queue_no)
+{
+	int bit = (ch_no & 0x7) * 4;
+
+	/* default to low priority queue */
+	if (queue_no == EVENTQ_DEFAULT)
+		queue_no = edma_cc[ctlr]->default_queue;
+
+	queue_no &= 7;
+	edma_modify_array(ctlr, EDMA_DMAQNUM, (ch_no >> 3),
+			~(0x7 << bit), queue_no << bit);
+}
+
+static void __init map_queue_tc(unsigned ctlr, int queue_no, int tc_no)
+{
+	int bit = queue_no * 4;
+	edma_modify(ctlr, EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit));
+}
+
+static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,
+		int priority)
+{
+	int bit = queue_no * 4;
+	edma_modify(ctlr, EDMA_QUEPRI, ~(0x7 << bit),
+			((priority & 0x7) << bit));
+}
+
+/**
+ * map_dmach_param - Maps channel number to param entry number
+ *
+ * This maps the dma channel number to param entry numberter. In
+ * other words using the DMA channel mapping registers a param entry
+ * can be mapped to any channel
+ *
+ * Callers are responsible for ensuring the channel mapping logic is
+ * included in that particular EDMA variant (Eg : dm646x)
+ *
+ */
+static void __init map_dmach_param(unsigned ctlr)
+{
+	int i;
+	for (i = 0; i < EDMA_MAX_DMACH; i++)
+		edma_write_array(ctlr, EDMA_DCHMAP , i , (i << 5));
+}
+
+static inline void
+setup_dma_interrupt(unsigned lch,
+	void (*callback)(unsigned channel, u16 ch_status, void *data),
+	void *data)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(lch);
+	lch = EDMA_CHAN_SLOT(lch);
+
+	if (!callback)
+		edma_shadow0_write_array(ctlr, SH_IECR, lch >> 5,
+				BIT(lch & 0x1f));
+
+	edma_cc[ctlr]->intr_data[lch].callback = callback;
+	edma_cc[ctlr]->intr_data[lch].data = data;
+
+	if (callback) {
+		edma_shadow0_write_array(ctlr, SH_ICR, lch >> 5,
+				BIT(lch & 0x1f));
+		edma_shadow0_write_array(ctlr, SH_IESR, lch >> 5,
+				BIT(lch & 0x1f));
+	}
+}
+
+static int irq2ctlr(int irq)
+{
+	if (irq >= edma_cc[0]->irq_res_start && irq <= edma_cc[0]->irq_res_end)
+		return 0;
+	else if (irq >= edma_cc[1]->irq_res_start &&
+		irq <= edma_cc[1]->irq_res_end)
+		return 1;
+
+	return -1;
+}
+
+/******************************************************************************
+ *
+ * DMA interrupt handler
+ *
+ *****************************************************************************/
+static irqreturn_t dma_irq_handler(int irq, void *data)
+{
+	int ctlr;
+	u32 sh_ier;
+	u32 sh_ipr;
+	u32 bank;
+
+	ctlr = irq2ctlr(irq);
+	if (ctlr < 0)
+		return IRQ_NONE;
+
+	dev_dbg(data, "dma_irq_handler\n");
+
+	sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 0);
+	if (!sh_ipr) {
+		sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 1);
+		if (!sh_ipr)
+			return IRQ_NONE;
+		sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 1);
+		bank = 1;
+	} else {
+		sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 0);
+		bank = 0;
+	}
+
+	do {
+		u32 slot;
+		u32 channel;
+
+		dev_dbg(data, "IPR%d %08x\n", bank, sh_ipr);
+
+		slot = __ffs(sh_ipr);
+		sh_ipr &= ~(BIT(slot));
+
+		if (sh_ier & BIT(slot)) {
+			channel = (bank << 5) | slot;
+			/* Clear the corresponding IPR bits */
+			edma_shadow0_write_array(ctlr, SH_ICR, bank,
+					BIT(slot));
+			if (edma_cc[ctlr]->intr_data[channel].callback)
+				edma_cc[ctlr]->intr_data[channel].callback(
+					channel, DMA_COMPLETE,
+					edma_cc[ctlr]->intr_data[channel].data);
+		}
+	} while (sh_ipr);
+
+	edma_shadow0_write(ctlr, SH_IEVAL, 1);
+	return IRQ_HANDLED;
+}
+
+/******************************************************************************
+ *
+ * DMA error interrupt handler
+ *
+ *****************************************************************************/
+static irqreturn_t dma_ccerr_handler(int irq, void *data)
+{
+	int i;
+	int ctlr;
+	unsigned int cnt = 0;
+
+	ctlr = irq2ctlr(irq);
+	if (ctlr < 0)
+		return IRQ_NONE;
+
+	dev_dbg(data, "dma_ccerr_handler\n");
+
+	if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
+	    (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
+	    (edma_read(ctlr, EDMA_QEMR) == 0) &&
+	    (edma_read(ctlr, EDMA_CCERR) == 0))
+		return IRQ_NONE;
+
+	while (1) {
+		int j = -1;
+		if (edma_read_array(ctlr, EDMA_EMR, 0))
+			j = 0;
+		else if (edma_read_array(ctlr, EDMA_EMR, 1))
+			j = 1;
+		if (j >= 0) {
+			dev_dbg(data, "EMR%d %08x\n", j,
+					edma_read_array(ctlr, EDMA_EMR, j));
+			for (i = 0; i < 32; i++) {
+				int k = (j << 5) + i;
+				if (edma_read_array(ctlr, EDMA_EMR, j) &
+							BIT(i)) {
+					/* Clear the corresponding EMR bits */
+					edma_write_array(ctlr, EDMA_EMCR, j,
+							BIT(i));
+					/* Clear any SER */
+					edma_shadow0_write_array(ctlr, SH_SECR,
+								j, BIT(i));
+					if (edma_cc[ctlr]->intr_data[k].
+								callback) {
+						edma_cc[ctlr]->intr_data[k].
+						callback(k,
+						DMA_CC_ERROR,
+						edma_cc[ctlr]->intr_data
+						[k].data);
+					}
+				}
+			}
+		} else if (edma_read(ctlr, EDMA_QEMR)) {
+			dev_dbg(data, "QEMR %02x\n",
+				edma_read(ctlr, EDMA_QEMR));
+			for (i = 0; i < 8; i++) {
+				if (edma_read(ctlr, EDMA_QEMR) & BIT(i)) {
+					/* Clear the corresponding IPR bits */
+					edma_write(ctlr, EDMA_QEMCR, BIT(i));
+					edma_shadow0_write(ctlr, SH_QSECR,
+								BIT(i));
+
+					/* NOTE:  not reported!! */
+				}
+			}
+		} else if (edma_read(ctlr, EDMA_CCERR)) {
+			dev_dbg(data, "CCERR %08x\n",
+				edma_read(ctlr, EDMA_CCERR));
+			/* FIXME:  CCERR.BIT(16) ignored!  much better
+			 * to just write CCERRCLR with CCERR value...
+			 */
+			for (i = 0; i < 8; i++) {
+				if (edma_read(ctlr, EDMA_CCERR) & BIT(i)) {
+					/* Clear the corresponding IPR bits */
+					edma_write(ctlr, EDMA_CCERRCLR, BIT(i));
+
+					/* NOTE:  not reported!! */
+				}
+			}
+		}
+		if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
+		    (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
+		    (edma_read(ctlr, EDMA_QEMR) == 0) &&
+		    (edma_read(ctlr, EDMA_CCERR) == 0))
+			break;
+		cnt++;
+		if (cnt > 10)
+			break;
+	}
+	edma_write(ctlr, EDMA_EEVAL, 1);
+	return IRQ_HANDLED;
+}
+
+static int reserve_contiguous_slots(int ctlr, unsigned int id,
+				     unsigned int num_slots,
+				     unsigned int start_slot)
+{
+	int i, j;
+	unsigned int count = num_slots;
+	int stop_slot = start_slot;
+	DECLARE_BITMAP(tmp_inuse, EDMA_MAX_PARAMENTRY);
+
+	for (i = start_slot; i < edma_cc[ctlr]->num_slots; ++i) {
+		j = EDMA_CHAN_SLOT(i);
+		if (!test_and_set_bit(j, edma_cc[ctlr]->edma_inuse)) {
+			/* Record our current beginning slot */
+			if (count == num_slots)
+				stop_slot = i;
+
+			count--;
+			set_bit(j, tmp_inuse);
+
+			if (count == 0)
+				break;
+		} else {
+			clear_bit(j, tmp_inuse);
+
+			if (id == EDMA_CONT_PARAMS_FIXED_EXACT) {
+				stop_slot = i;
+				break;
+			} else {
+				count = num_slots;
+			}
+		}
+	}
+
+	/*
+	 * We have to clear any bits that we set
+	 * if we run out parameter RAM slots, i.e we do find a set
+	 * of contiguous parameter RAM slots but do not find the exact number
+	 * requested as we may reach the total number of parameter RAM slots
+	 */
+	if (i == edma_cc[ctlr]->num_slots)
+		stop_slot = i;
+
+	j = start_slot;
+	for_each_set_bit_from(j, tmp_inuse, stop_slot)
+		clear_bit(j, edma_cc[ctlr]->edma_inuse);
+
+	if (count)
+		return -EBUSY;
+
+	for (j = i - num_slots + 1; j <= i; ++j)
+		memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(j),
+			&dummy_paramset, PARM_SIZE);
+
+	return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1);
+}
+
+static int prepare_unused_channel_list(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int i, ctlr;
+
+	for (i = 0; i < pdev->num_resources; i++) {
+		if ((pdev->resource[i].flags & IORESOURCE_DMA) &&
+				(int)pdev->resource[i].start >= 0) {
+			ctlr = EDMA_CTLR(pdev->resource[i].start);
+			clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start),
+					edma_cc[ctlr]->edma_unused);
+		}
+	}
+
+	return 0;
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* Resource alloc/free:  dma channels, parameter RAM slots */
+
+/**
+ * edma_alloc_channel - allocate DMA channel and paired parameter RAM
+ * @channel: specific channel to allocate; negative for "any unmapped channel"
+ * @callback: optional; to be issued on DMA completion or errors
+ * @data: passed to callback
+ * @eventq_no: an EVENTQ_* constant, used to choose which Transfer
+ *	Controller (TC) executes requests using this channel.  Use
+ *	EVENTQ_DEFAULT unless you really need a high priority queue.
+ *
+ * This allocates a DMA channel and its associated parameter RAM slot.
+ * The parameter RAM is initialized to hold a dummy transfer.
+ *
+ * Normal use is to pass a specific channel number as @channel, to make
+ * use of hardware events mapped to that channel.  When the channel will
+ * be used only for software triggering or event chaining, channels not
+ * mapped to hardware events (or mapped to unused events) are preferable.
+ *
+ * DMA transfers start from a channel using edma_start(), or by
+ * chaining.  When the transfer described in that channel's parameter RAM
+ * slot completes, that slot's data may be reloaded through a link.
+ *
+ * DMA errors are only reported to the @callback associated with the
+ * channel driving that transfer, but transfer completion callbacks can
+ * be sent to another channel under control of the TCC field in
+ * the option word of the transfer's parameter RAM set.  Drivers must not
+ * use DMA transfer completion callbacks for channels they did not allocate.
+ * (The same applies to TCC codes used in transfer chaining.)
+ *
+ * Returns the number of the channel, else negative errno.
+ */
+int edma_alloc_channel(int channel,
+		void (*callback)(unsigned channel, u16 ch_status, void *data),
+		void *data,
+		enum dma_event_q eventq_no)
+{
+	unsigned i, done = 0, ctlr = 0;
+	int ret = 0;
+
+	/*
+	 * Scan all the platform devices to find out the EDMA channels
+	 * used and clear them in the unused list, making the rest
+	 * available for ARM usage.
+	 *
+	 * Note: We do this every time now, since when devices are
+	 * dynamically created the old unused list must be updated.
+	 */
+	ret = bus_for_each_dev(&platform_bus_type, NULL, NULL,
+			prepare_unused_channel_list);
+	if (ret < 0)
+		return ret;
+
+	if (channel >= 0) {
+		ctlr = EDMA_CTLR(channel);
+		channel = EDMA_CHAN_SLOT(channel);
+	}
+
+	if (channel < 0) {
+		for (i = 0; i < arch_num_cc; i++) {
+			channel = 0;
+			for (;;) {
+				channel = find_next_bit(edma_cc[i]->edma_unused,
+						edma_cc[i]->num_channels,
+						channel);
+				if (channel == edma_cc[i]->num_channels)
+					break;
+				if (!test_and_set_bit(channel,
+						edma_cc[i]->edma_inuse)) {
+					done = 1;
+					ctlr = i;
+					break;
+				}
+				channel++;
+			}
+			if (done)
+				break;
+		}
+		if (!done)
+			return -ENOMEM;
+	} else if (channel >= edma_cc[ctlr]->num_channels) {
+		return -EINVAL;
+	} else if (test_and_set_bit(channel, edma_cc[ctlr]->edma_inuse)) {
+		return -EBUSY;
+	}
+
+	/* ensure access through shadow region 0 */
+	edma_or_array2(ctlr, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f));
+
+	/* ensure no events are pending */
+	edma_stop(EDMA_CTLR_CHAN(ctlr, channel));
+	memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel),
+			&dummy_paramset, PARM_SIZE);
+
+	if (callback)
+		setup_dma_interrupt(EDMA_CTLR_CHAN(ctlr, channel),
+					callback, data);
+
+	map_dmach_queue(ctlr, channel, eventq_no);
+
+	return EDMA_CTLR_CHAN(ctlr, channel);
+}
+EXPORT_SYMBOL(edma_alloc_channel);
+
+
+/**
+ * edma_free_channel - deallocate DMA channel
+ * @channel: dma channel returned from edma_alloc_channel()
+ *
+ * This deallocates the DMA channel and associated parameter RAM slot
+ * allocated by edma_alloc_channel().
+ *
+ * Callers are responsible for ensuring the channel is inactive, and
+ * will not be reactivated by linking, chaining, or software calls to
+ * edma_start().
+ */
+void edma_free_channel(unsigned channel)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(channel);
+	channel = EDMA_CHAN_SLOT(channel);
+
+	if (channel >= edma_cc[ctlr]->num_channels)
+		return;
+
+	setup_dma_interrupt(channel, NULL, NULL);
+	/* REVISIT should probably take out of shadow region 0 */
+
+	memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel),
+			&dummy_paramset, PARM_SIZE);
+	clear_bit(channel, edma_cc[ctlr]->edma_inuse);
+}
+EXPORT_SYMBOL(edma_free_channel);
+
+/**
+ * edma_alloc_slot - allocate DMA parameter RAM
+ * @slot: specific slot to allocate; negative for "any unused slot"
+ *
+ * This allocates a parameter RAM slot, initializing it to hold a
+ * dummy transfer.  Slots allocated using this routine have not been
+ * mapped to a hardware DMA channel, and will normally be used by
+ * linking to them from a slot associated with a DMA channel.
+ *
+ * Normal use is to pass EDMA_SLOT_ANY as the @slot, but specific
+ * slots may be allocated on behalf of DSP firmware.
+ *
+ * Returns the number of the slot, else negative errno.
+ */
+int edma_alloc_slot(unsigned ctlr, int slot)
+{
+	if (!edma_cc[ctlr])
+		return -EINVAL;
+
+	if (slot >= 0)
+		slot = EDMA_CHAN_SLOT(slot);
+
+	if (slot < 0) {
+		slot = edma_cc[ctlr]->num_channels;
+		for (;;) {
+			slot = find_next_zero_bit(edma_cc[ctlr]->edma_inuse,
+					edma_cc[ctlr]->num_slots, slot);
+			if (slot == edma_cc[ctlr]->num_slots)
+				return -ENOMEM;
+			if (!test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse))
+				break;
+		}
+	} else if (slot < edma_cc[ctlr]->num_channels ||
+			slot >= edma_cc[ctlr]->num_slots) {
+		return -EINVAL;
+	} else if (test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse)) {
+		return -EBUSY;
+	}
+
+	memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
+			&dummy_paramset, PARM_SIZE);
+
+	return EDMA_CTLR_CHAN(ctlr, slot);
+}
+EXPORT_SYMBOL(edma_alloc_slot);
+
+/**
+ * edma_free_slot - deallocate DMA parameter RAM
+ * @slot: parameter RAM slot returned from edma_alloc_slot()
+ *
+ * This deallocates the parameter RAM slot allocated by edma_alloc_slot().
+ * Callers are responsible for ensuring the slot is inactive, and will
+ * not be activated.
+ */
+void edma_free_slot(unsigned slot)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(slot);
+	slot = EDMA_CHAN_SLOT(slot);
+
+	if (slot < edma_cc[ctlr]->num_channels ||
+		slot >= edma_cc[ctlr]->num_slots)
+		return;
+
+	memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
+			&dummy_paramset, PARM_SIZE);
+	clear_bit(slot, edma_cc[ctlr]->edma_inuse);
+}
+EXPORT_SYMBOL(edma_free_slot);
+
+
+/**
+ * edma_alloc_cont_slots- alloc contiguous parameter RAM slots
+ * The API will return the starting point of a set of
+ * contiguous parameter RAM slots that have been requested
+ *
+ * @id: can only be EDMA_CONT_PARAMS_ANY or EDMA_CONT_PARAMS_FIXED_EXACT
+ * or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
+ * @count: number of contiguous Paramter RAM slots
+ * @slot  - the start value of Parameter RAM slot that should be passed if id
+ * is EDMA_CONT_PARAMS_FIXED_EXACT or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
+ *
+ * If id is EDMA_CONT_PARAMS_ANY then the API starts looking for a set of
+ * contiguous Parameter RAM slots from parameter RAM 64 in the case of
+ * DaVinci SOCs and 32 in the case of DA8xx SOCs.
+ *
+ * If id is EDMA_CONT_PARAMS_FIXED_EXACT then the API starts looking for a
+ * set of contiguous parameter RAM slots from the "slot" that is passed as an
+ * argument to the API.
+ *
+ * If id is EDMA_CONT_PARAMS_FIXED_NOT_EXACT then the API initially tries
+ * starts looking for a set of contiguous parameter RAMs from the "slot"
+ * that is passed as an argument to the API. On failure the API will try to
+ * find a set of contiguous Parameter RAM slots from the remaining Parameter
+ * RAM slots
+ */
+int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count)
+{
+	/*
+	 * The start slot requested should be greater than
+	 * the number of channels and lesser than the total number
+	 * of slots
+	 */
+	if ((id != EDMA_CONT_PARAMS_ANY) &&
+		(slot < edma_cc[ctlr]->num_channels ||
+		slot >= edma_cc[ctlr]->num_slots))
+		return -EINVAL;
+
+	/*
+	 * The number of parameter RAM slots requested cannot be less than 1
+	 * and cannot be more than the number of slots minus the number of
+	 * channels
+	 */
+	if (count < 1 || count >
+		(edma_cc[ctlr]->num_slots - edma_cc[ctlr]->num_channels))
+		return -EINVAL;
+
+	switch (id) {
+	case EDMA_CONT_PARAMS_ANY:
+		return reserve_contiguous_slots(ctlr, id, count,
+						 edma_cc[ctlr]->num_channels);
+	case EDMA_CONT_PARAMS_FIXED_EXACT:
+	case EDMA_CONT_PARAMS_FIXED_NOT_EXACT:
+		return reserve_contiguous_slots(ctlr, id, count, slot);
+	default:
+		return -EINVAL;
+	}
+
+}
+EXPORT_SYMBOL(edma_alloc_cont_slots);
+
+/**
+ * edma_free_cont_slots - deallocate DMA parameter RAM slots
+ * @slot: first parameter RAM of a set of parameter RAM slots to be freed
+ * @count: the number of contiguous parameter RAM slots to be freed
+ *
+ * This deallocates the parameter RAM slots allocated by
+ * edma_alloc_cont_slots.
+ * Callers/applications need to keep track of sets of contiguous
+ * parameter RAM slots that have been allocated using the edma_alloc_cont_slots
+ * API.
+ * Callers are responsible for ensuring the slots are inactive, and will
+ * not be activated.
+ */
+int edma_free_cont_slots(unsigned slot, int count)
+{
+	unsigned ctlr, slot_to_free;
+	int i;
+
+	ctlr = EDMA_CTLR(slot);
+	slot = EDMA_CHAN_SLOT(slot);
+
+	if (slot < edma_cc[ctlr]->num_channels ||
+		slot >= edma_cc[ctlr]->num_slots ||
+		count < 1)
+		return -EINVAL;
+
+	for (i = slot; i < slot + count; ++i) {
+		ctlr = EDMA_CTLR(i);
+		slot_to_free = EDMA_CHAN_SLOT(i);
+
+		memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot_to_free),
+			&dummy_paramset, PARM_SIZE);
+		clear_bit(slot_to_free, edma_cc[ctlr]->edma_inuse);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(edma_free_cont_slots);
+
+/*-----------------------------------------------------------------------*/
+
+/* Parameter RAM operations (i) -- read/write partial slots */
+
+/**
+ * edma_set_src - set initial DMA source address in parameter RAM slot
+ * @slot: parameter RAM slot being configured
+ * @src_port: physical address of source (memory, controller FIFO, etc)
+ * @addressMode: INCR, except in very rare cases
+ * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
+ *	width to use when addressing the fifo (e.g. W8BIT, W32BIT)
+ *
+ * Note that the source address is modified during the DMA transfer
+ * according to edma_set_src_index().
+ */
+void edma_set_src(unsigned slot, dma_addr_t src_port,
+				enum address_mode mode, enum fifo_width width)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(slot);
+	slot = EDMA_CHAN_SLOT(slot);
+
+	if (slot < edma_cc[ctlr]->num_slots) {
+		unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot);
+
+		if (mode) {
+			/* set SAM and program FWID */
+			i = (i & ~(EDMA_FWID)) | (SAM | ((width & 0x7) << 8));
+		} else {
+			/* clear SAM */
+			i &= ~SAM;
+		}
+		edma_parm_write(ctlr, PARM_OPT, slot, i);
+
+		/* set the source port address
+		   in source register of param structure */
+		edma_parm_write(ctlr, PARM_SRC, slot, src_port);
+	}
+}
+EXPORT_SYMBOL(edma_set_src);
+
+/**
+ * edma_set_dest - set initial DMA destination address in parameter RAM slot
+ * @slot: parameter RAM slot being configured
+ * @dest_port: physical address of destination (memory, controller FIFO, etc)
+ * @addressMode: INCR, except in very rare cases
+ * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
+ *	width to use when addressing the fifo (e.g. W8BIT, W32BIT)
+ *
+ * Note that the destination address is modified during the DMA transfer
+ * according to edma_set_dest_index().
+ */
+void edma_set_dest(unsigned slot, dma_addr_t dest_port,
+				 enum address_mode mode, enum fifo_width width)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(slot);
+	slot = EDMA_CHAN_SLOT(slot);
+
+	if (slot < edma_cc[ctlr]->num_slots) {
+		unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot);
+
+		if (mode) {
+			/* set DAM and program FWID */
+			i = (i & ~(EDMA_FWID)) | (DAM | ((width & 0x7) << 8));
+		} else {
+			/* clear DAM */
+			i &= ~DAM;
+		}
+		edma_parm_write(ctlr, PARM_OPT, slot, i);
+		/* set the destination port address
+		   in dest register of param structure */
+		edma_parm_write(ctlr, PARM_DST, slot, dest_port);
+	}
+}
+EXPORT_SYMBOL(edma_set_dest);
+
+/**
+ * edma_get_position - returns the current transfer points
+ * @slot: parameter RAM slot being examined
+ * @src: pointer to source port position
+ * @dst: pointer to destination port position
+ *
+ * Returns current source and destination addresses for a particular
+ * parameter RAM slot.  Its channel should not be active when this is called.
+ */
+void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst)
+{
+	struct edmacc_param temp;
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(slot);
+	slot = EDMA_CHAN_SLOT(slot);
+
+	edma_read_slot(EDMA_CTLR_CHAN(ctlr, slot), &temp);
+	if (src != NULL)
+		*src = temp.src;
+	if (dst != NULL)
+		*dst = temp.dst;
+}
+EXPORT_SYMBOL(edma_get_position);
+
+/**
+ * edma_set_src_index - configure DMA source address indexing
+ * @slot: parameter RAM slot being configured
+ * @src_bidx: byte offset between source arrays in a frame
+ * @src_cidx: byte offset between source frames in a block
+ *
+ * Offsets are specified to support either contiguous or discontiguous
+ * memory transfers, or repeated access to a hardware register, as needed.
+ * When accessing hardware registers, both offsets are normally zero.
+ */
+void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(slot);
+	slot = EDMA_CHAN_SLOT(slot);
+
+	if (slot < edma_cc[ctlr]->num_slots) {
+		edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot,
+				0xffff0000, src_bidx);
+		edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot,
+				0xffff0000, src_cidx);
+	}
+}
+EXPORT_SYMBOL(edma_set_src_index);
+
+/**
+ * edma_set_dest_index - configure DMA destination address indexing
+ * @slot: parameter RAM slot being configured
+ * @dest_bidx: byte offset between destination arrays in a frame
+ * @dest_cidx: byte offset between destination frames in a block
+ *
+ * Offsets are specified to support either contiguous or discontiguous
+ * memory transfers, or repeated access to a hardware register, as needed.
+ * When accessing hardware registers, both offsets are normally zero.
+ */
+void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(slot);
+	slot = EDMA_CHAN_SLOT(slot);
+
+	if (slot < edma_cc[ctlr]->num_slots) {
+		edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot,
+				0x0000ffff, dest_bidx << 16);
+		edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot,
+				0x0000ffff, dest_cidx << 16);
+	}
+}
+EXPORT_SYMBOL(edma_set_dest_index);
+
+/**
+ * edma_set_transfer_params - configure DMA transfer parameters
+ * @slot: parameter RAM slot being configured
+ * @acnt: how many bytes per array (at least one)
+ * @bcnt: how many arrays per frame (at least one)
+ * @ccnt: how many frames per block (at least one)
+ * @bcnt_rld: used only for A-Synchronized transfers; this specifies
+ *	the value to reload into bcnt when it decrements to zero
+ * @sync_mode: ASYNC or ABSYNC
+ *
+ * See the EDMA3 documentation to understand how to configure and link
+ * transfers using the fields in PaRAM slots.  If you are not doing it
+ * all at once with edma_write_slot(), you will use this routine
+ * plus two calls each for source and destination, setting the initial
+ * address and saying how to index that address.
+ *
+ * An example of an A-Synchronized transfer is a serial link using a
+ * single word shift register.  In that case, @acnt would be equal to
+ * that word size; the serial controller issues a DMA synchronization
+ * event to transfer each word, and memory access by the DMA transfer
+ * controller will be word-at-a-time.
+ *
+ * An example of an AB-Synchronized transfer is a device using a FIFO.
+ * In that case, @acnt equals the FIFO width and @bcnt equals its depth.
+ * The controller with the FIFO issues DMA synchronization events when
+ * the FIFO threshold is reached, and the DMA transfer controller will
+ * transfer one frame to (or from) the FIFO.  It will probably use
+ * efficient burst modes to access memory.
+ */
+void edma_set_transfer_params(unsigned slot,
+		u16 acnt, u16 bcnt, u16 ccnt,
+		u16 bcnt_rld, enum sync_dimension sync_mode)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(slot);
+	slot = EDMA_CHAN_SLOT(slot);
+
+	if (slot < edma_cc[ctlr]->num_slots) {
+		edma_parm_modify(ctlr, PARM_LINK_BCNTRLD, slot,
+				0x0000ffff, bcnt_rld << 16);
+		if (sync_mode == ASYNC)
+			edma_parm_and(ctlr, PARM_OPT, slot, ~SYNCDIM);
+		else
+			edma_parm_or(ctlr, PARM_OPT, slot, SYNCDIM);
+		/* Set the acount, bcount, ccount registers */
+		edma_parm_write(ctlr, PARM_A_B_CNT, slot, (bcnt << 16) | acnt);
+		edma_parm_write(ctlr, PARM_CCNT, slot, ccnt);
+	}
+}
+EXPORT_SYMBOL(edma_set_transfer_params);
+
+/**
+ * edma_link - link one parameter RAM slot to another
+ * @from: parameter RAM slot originating the link
+ * @to: parameter RAM slot which is the link target
+ *
+ * The originating slot should not be part of any active DMA transfer.
+ */
+void edma_link(unsigned from, unsigned to)
+{
+	unsigned ctlr_from, ctlr_to;
+
+	ctlr_from = EDMA_CTLR(from);
+	from = EDMA_CHAN_SLOT(from);
+	ctlr_to = EDMA_CTLR(to);
+	to = EDMA_CHAN_SLOT(to);
+
+	if (from >= edma_cc[ctlr_from]->num_slots)
+		return;
+	if (to >= edma_cc[ctlr_to]->num_slots)
+		return;
+	edma_parm_modify(ctlr_from, PARM_LINK_BCNTRLD, from, 0xffff0000,
+				PARM_OFFSET(to));
+}
+EXPORT_SYMBOL(edma_link);
+
+/**
+ * edma_unlink - cut link from one parameter RAM slot
+ * @from: parameter RAM slot originating the link
+ *
+ * The originating slot should not be part of any active DMA transfer.
+ * Its link is set to 0xffff.
+ */
+void edma_unlink(unsigned from)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(from);
+	from = EDMA_CHAN_SLOT(from);
+
+	if (from >= edma_cc[ctlr]->num_slots)
+		return;
+	edma_parm_or(ctlr, PARM_LINK_BCNTRLD, from, 0xffff);
+}
+EXPORT_SYMBOL(edma_unlink);
+
+/*-----------------------------------------------------------------------*/
+
+/* Parameter RAM operations (ii) -- read/write whole parameter sets */
+
+/**
+ * edma_write_slot - write parameter RAM data for slot
+ * @slot: number of parameter RAM slot being modified
+ * @param: data to be written into parameter RAM slot
+ *
+ * Use this to assign all parameters of a transfer at once.  This
+ * allows more efficient setup of transfers than issuing multiple
+ * calls to set up those parameters in small pieces, and provides
+ * complete control over all transfer options.
+ */
+void edma_write_slot(unsigned slot, const struct edmacc_param *param)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(slot);
+	slot = EDMA_CHAN_SLOT(slot);
+
+	if (slot >= edma_cc[ctlr]->num_slots)
+		return;
+	memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot), param,
+			PARM_SIZE);
+}
+EXPORT_SYMBOL(edma_write_slot);
+
+/**
+ * edma_read_slot - read parameter RAM data from slot
+ * @slot: number of parameter RAM slot being copied
+ * @param: where to store copy of parameter RAM data
+ *
+ * Use this to read data from a parameter RAM slot, perhaps to
+ * save them as a template for later reuse.
+ */
+void edma_read_slot(unsigned slot, struct edmacc_param *param)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(slot);
+	slot = EDMA_CHAN_SLOT(slot);
+
+	if (slot >= edma_cc[ctlr]->num_slots)
+		return;
+	memcpy_fromio(param, edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
+			PARM_SIZE);
+}
+EXPORT_SYMBOL(edma_read_slot);
+
+/*-----------------------------------------------------------------------*/
+
+/* Various EDMA channel control operations */
+
+/**
+ * edma_pause - pause dma on a channel
+ * @channel: on which edma_start() has been called
+ *
+ * This temporarily disables EDMA hardware events on the specified channel,
+ * preventing them from triggering new transfers on its behalf
+ */
+void edma_pause(unsigned channel)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(channel);
+	channel = EDMA_CHAN_SLOT(channel);
+
+	if (channel < edma_cc[ctlr]->num_channels) {
+		unsigned int mask = BIT(channel & 0x1f);
+
+		edma_shadow0_write_array(ctlr, SH_EECR, channel >> 5, mask);
+	}
+}
+EXPORT_SYMBOL(edma_pause);
+
+/**
+ * edma_resume - resumes dma on a paused channel
+ * @channel: on which edma_pause() has been called
+ *
+ * This re-enables EDMA hardware events on the specified channel.
+ */
+void edma_resume(unsigned channel)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(channel);
+	channel = EDMA_CHAN_SLOT(channel);
+
+	if (channel < edma_cc[ctlr]->num_channels) {
+		unsigned int mask = BIT(channel & 0x1f);
+
+		edma_shadow0_write_array(ctlr, SH_EESR, channel >> 5, mask);
+	}
+}
+EXPORT_SYMBOL(edma_resume);
+
+/**
+ * edma_start - start dma on a channel
+ * @channel: channel being activated
+ *
+ * Channels with event associations will be triggered by their hardware
+ * events, and channels without such associations will be triggered by
+ * software.  (At this writing there is no interface for using software
+ * triggers except with channels that don't support hardware triggers.)
+ *
+ * Returns zero on success, else negative errno.
+ */
+int edma_start(unsigned channel)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(channel);
+	channel = EDMA_CHAN_SLOT(channel);
+
+	if (channel < edma_cc[ctlr]->num_channels) {
+		int j = channel >> 5;
+		unsigned int mask = BIT(channel & 0x1f);
+
+		/* EDMA channels without event association */
+		if (test_bit(channel, edma_cc[ctlr]->edma_unused)) {
+			pr_debug("EDMA: ESR%d %08x\n", j,
+				edma_shadow0_read_array(ctlr, SH_ESR, j));
+			edma_shadow0_write_array(ctlr, SH_ESR, j, mask);
+			return 0;
+		}
+
+		/* EDMA channel with event association */
+		pr_debug("EDMA: ER%d %08x\n", j,
+			edma_shadow0_read_array(ctlr, SH_ER, j));
+		/* Clear any pending event or error */
+		edma_write_array(ctlr, EDMA_ECR, j, mask);
+		edma_write_array(ctlr, EDMA_EMCR, j, mask);
+		/* Clear any SER */
+		edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
+		edma_shadow0_write_array(ctlr, SH_EESR, j, mask);
+		pr_debug("EDMA: EER%d %08x\n", j,
+			edma_shadow0_read_array(ctlr, SH_EER, j));
+		return 0;
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(edma_start);
+
+/**
+ * edma_stop - stops dma on the channel passed
+ * @channel: channel being deactivated
+ *
+ * When @lch is a channel, any active transfer is paused and
+ * all pending hardware events are cleared.  The current transfer
+ * may not be resumed, and the channel's Parameter RAM should be
+ * reinitialized before being reused.
+ */
+void edma_stop(unsigned channel)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(channel);
+	channel = EDMA_CHAN_SLOT(channel);
+
+	if (channel < edma_cc[ctlr]->num_channels) {
+		int j = channel >> 5;
+		unsigned int mask = BIT(channel & 0x1f);
+
+		edma_shadow0_write_array(ctlr, SH_EECR, j, mask);
+		edma_shadow0_write_array(ctlr, SH_ECR, j, mask);
+		edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
+		edma_write_array(ctlr, EDMA_EMCR, j, mask);
+
+		pr_debug("EDMA: EER%d %08x\n", j,
+				edma_shadow0_read_array(ctlr, SH_EER, j));
+
+		/* REVISIT:  consider guarding against inappropriate event
+		 * chaining by overwriting with dummy_paramset.
+		 */
+	}
+}
+EXPORT_SYMBOL(edma_stop);
+
+/******************************************************************************
+ *
+ * It cleans ParamEntry qand bring back EDMA to initial state if media has
+ * been removed before EDMA has finished.It is usedful for removable media.
+ * Arguments:
+ *      ch_no     - channel no
+ *
+ * Return: zero on success, or corresponding error no on failure
+ *
+ * FIXME this should not be needed ... edma_stop() should suffice.
+ *
+ *****************************************************************************/
+
+void edma_clean_channel(unsigned channel)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(channel);
+	channel = EDMA_CHAN_SLOT(channel);
+
+	if (channel < edma_cc[ctlr]->num_channels) {
+		int j = (channel >> 5);
+		unsigned int mask = BIT(channel & 0x1f);
+
+		pr_debug("EDMA: EMR%d %08x\n", j,
+				edma_read_array(ctlr, EDMA_EMR, j));
+		edma_shadow0_write_array(ctlr, SH_ECR, j, mask);
+		/* Clear the corresponding EMR bits */
+		edma_write_array(ctlr, EDMA_EMCR, j, mask);
+		/* Clear any SER */
+		edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
+		edma_write(ctlr, EDMA_CCERRCLR, BIT(16) | BIT(1) | BIT(0));
+	}
+}
+EXPORT_SYMBOL(edma_clean_channel);
+
+/*
+ * edma_clear_event - clear an outstanding event on the DMA channel
+ * Arguments:
+ *	channel - channel number
+ */
+void edma_clear_event(unsigned channel)
+{
+	unsigned ctlr;
+
+	ctlr = EDMA_CTLR(channel);
+	channel = EDMA_CHAN_SLOT(channel);
+
+	if (channel >= edma_cc[ctlr]->num_channels)
+		return;
+	if (channel < 32)
+		edma_write(ctlr, EDMA_ECR, BIT(channel));
+	else
+		edma_write(ctlr, EDMA_ECRH, BIT(channel - 32));
+}
+EXPORT_SYMBOL(edma_clear_event);
+
+/*-----------------------------------------------------------------------*/
+static int edma_of_read_u32_to_s8_array(const struct device_node *np,
+					 const char *propname, s8 *out_values,
+					 size_t sz)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	const __be32 *val;
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+	if ((sz * sizeof(u32)) > prop->length)
+		return -EOVERFLOW;
+
+	val = prop->value;
+
+	while (sz--)
+		*out_values++ = (s8)(be32_to_cpup(val++) & 0xff);
+
+	/* Terminate it */
+	*out_values++ = -1;
+	*out_values++ = -1;
+
+	return 0;
+}
+
+static int edma_of_read_u32_to_s16_array(const struct device_node *np,
+					 const char *propname, s16 *out_values,
+					 size_t sz)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	const __be32 *val;
+
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+	if ((sz * sizeof(u32)) > prop->length)
+		return -EOVERFLOW;
+
+	val = prop->value;
+
+	while (sz--)
+		*out_values++ = (s16)(be32_to_cpup(val++) & 0xffff);
+
+	/* Terminate it */
+	*out_values++ = -1;
+	*out_values++ = -1;
+
+	return 0;
+}
+
+static int edma_xbar_event_map(struct device *dev,
+			       struct device_node *node,
+			       struct edma_soc_info *pdata, int len)
+{
+	int ret = 0;
+	int i;
+	struct resource res;
+	void *xbar;
+	const s16 (*xbar_chans)[2];
+	u32 shift, offset, mux;
+
+	xbar_chans = devm_kzalloc(dev,
+				  len/sizeof(s16) + 2*sizeof(s16),
+				  GFP_KERNEL);
+	if (!xbar_chans)
+		return -ENOMEM;
+
+	ret = of_address_to_resource(node, 1, &res);
+	if (IS_ERR_VALUE(ret))
+		return -EIO;
+
+	xbar = devm_ioremap(dev, res.start, resource_size(&res));
+	if (!xbar)
+		return -ENOMEM;
+
+	ret = edma_of_read_u32_to_s16_array(node,
+					    "ti,edma-xbar-event-map",
+					    (s16 *)xbar_chans,
+					    len/sizeof(u32));
+	if (IS_ERR_VALUE(ret))
+		return -EIO;
+
+	for (i = 0; xbar_chans[i][0] != -1; i++) {
+		shift = (xbar_chans[i][1] % 4) * 8;
+		offset = xbar_chans[i][1] >> 2;
+		offset <<= 2;
+		mux = readl((void *)((u32)xbar + offset));
+		mux &= ~(0xff << shift);
+		mux |= xbar_chans[i][0] << shift;
+		writel(mux, (void *)((u32)xbar + offset));
+	}
+
+	pdata->xbar_chans = xbar_chans;
+
+	return 0;
+}
+
+static int edma_of_parse_dt(struct device *dev,
+			    struct device_node *node,
+			    struct edma_soc_info *pdata)
+{
+	int ret = 0;
+	u32 value;
+	struct property *prop;
+	size_t sz;
+	struct edma_rsv_info *rsv_info;
+	const s16 (*rsv_chans)[2], (*rsv_slots)[2];
+	const s8 (*queue_tc_map)[2], (*queue_priority_map)[2];
+
+	memset(pdata, 0, sizeof(struct edma_soc_info));
+
+	ret = of_property_read_u32(node, "dma-channels", &value);
+	if (ret < 0)
+		return ret;
+	pdata->n_channel = value;
+
+	ret = of_property_read_u32(node, "ti,edma-regions", &value);
+	if (ret < 0)
+		return ret;
+	pdata->n_region = value;
+
+	ret = of_property_read_u32(node, "ti,edma-slots", &value);
+	if (ret < 0)
+		return ret;
+	pdata->n_slot = value;
+
+	pdata->n_cc = 1;
+	pdata->n_tc = 3;
+
+	rsv_info =
+		devm_kzalloc(dev, sizeof(struct edma_rsv_info), GFP_KERNEL);
+	if (!rsv_info)
+		return -ENOMEM;
+	pdata->rsv = rsv_info;
+
+	/* Build the reserved channel/slots arrays */
+	prop = of_find_property(node, "ti,edma-reserved-channels", &sz);
+	if (prop) {
+		rsv_chans = devm_kzalloc(dev,
+					 sz/sizeof(s16) + 2*sizeof(s16),
+					 GFP_KERNEL);
+		if (!rsv_chans)
+			return -ENOMEM;
+		pdata->rsv->rsv_chans = rsv_chans;
+
+		ret = edma_of_read_u32_to_s16_array(node,
+						    "ti,edma-reserved-channels",
+						    (s16 *)rsv_chans,
+						    sz/sizeof(u32));
+		if (ret < 0)
+			return ret;
+	}
+
+	prop = of_find_property(node, "ti,edma-reserved-slots", &sz);
+	if (prop) {
+		rsv_slots = devm_kzalloc(dev,
+					 sz/sizeof(s16) + 2*sizeof(s16),
+					 GFP_KERNEL);
+		if (!rsv_slots)
+			return -ENOMEM;
+		pdata->rsv->rsv_slots = rsv_slots;
+
+		ret = edma_of_read_u32_to_s16_array(node,
+						    "ti,edma-reserved-slots",
+						    (s16 *)rsv_slots,
+						    sz/sizeof(u32));
+		if (ret < 0)
+			return ret;
+	}
+
+	prop = of_find_property(node, "ti,edma-queue-tc-map", &sz);
+	if (!prop)
+		return -EINVAL;
+
+	queue_tc_map = devm_kzalloc(dev,
+				    sz/sizeof(s8) + 2*sizeof(s8),
+				    GFP_KERNEL);
+	if (!queue_tc_map)
+		return -ENOMEM;
+	pdata->queue_tc_mapping = queue_tc_map;
+
+	ret = edma_of_read_u32_to_s8_array(node,
+					   "ti,edma-queue-tc-map",
+					   (s8 *)queue_tc_map,
+					   sz/sizeof(u32));
+	if (ret < 0)
+		return ret;
+
+	prop = of_find_property(node, "ti,edma-queue-priority-map", &sz);
+	if (!prop)
+		return -EINVAL;
+
+	queue_priority_map = devm_kzalloc(dev,
+					  sz/sizeof(s8) + 2*sizeof(s8),
+					  GFP_KERNEL);
+	if (!queue_priority_map)
+		return -ENOMEM;
+	pdata->queue_priority_mapping = queue_priority_map;
+
+	ret = edma_of_read_u32_to_s8_array(node,
+					   "ti,edma-queue-tc-map",
+					   (s8 *)queue_priority_map,
+					   sz/sizeof(u32));
+	if (ret < 0)
+		return ret;
+
+	ret = of_property_read_u32(node, "ti,edma-default-queue", &value);
+	if (ret < 0)
+		return ret;
+	pdata->default_queue = value;
+
+	prop = of_find_property(node, "ti,edma-xbar-event-map", &sz);
+	if (prop)
+		ret = edma_xbar_event_map(dev, node, pdata, sz);
+
+	return ret;
+}
+
+static struct of_dma_filter_info edma_filter_info = {
+	.filter_fn = edma_filter_fn,
+};
+
+static int edma_probe(struct platform_device *pdev)
+{
+	struct edma_soc_info	**info = pdev->dev.platform_data;
+	struct edma_soc_info	*ninfo[EDMA_MAX_CC] = {NULL, NULL};
+	struct edma_soc_info	tmpinfo;
+	const s8		(*queue_priority_mapping)[2];
+	const s8		(*queue_tc_mapping)[2];
+	int			i, j, off, ln, found = 0;
+	int			status = -1;
+	const s16		(*rsv_chans)[2];
+	const s16		(*rsv_slots)[2];
+	const s16		(*xbar_chans)[2];
+	int			irq[EDMA_MAX_CC] = {0, 0};
+	int			err_irq[EDMA_MAX_CC] = {0, 0};
+	struct resource		*r[EDMA_MAX_CC] = {NULL, NULL};
+	struct resource		res[EDMA_MAX_CC];
+	resource_size_t		len[EDMA_MAX_CC];
+	char			res_name[10];
+	char			irq_name[10];
+	struct device_node	*node = pdev->dev.of_node;
+	struct device		*dev = &pdev->dev;
+	int			ret;
+
+	if (node) {
+		info = ninfo;
+		edma_of_parse_dt(dev, node, &tmpinfo);
+		info[0] = &tmpinfo;
+
+		dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap);
+		of_dma_controller_register(dev->of_node,
+					   of_dma_simple_xlate,
+					   &edma_filter_info);
+	}
+
+	if (!info)
+		return -ENODEV;
+
+	pm_runtime_enable(dev);
+	ret = pm_runtime_get_sync(dev);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(dev, "pm_runtime_get_sync() failed\n");
+		return ret;
+	}
+
+	for (j = 0; j < EDMA_MAX_CC; j++) {
+		if (!info[j]) {
+			if (!found)
+				return -ENODEV;
+			break;
+		}
+		if (node) {
+			ret = of_address_to_resource(node, j, &res[j]);
+			if (!IS_ERR_VALUE(ret))
+				r[j] = &res[j];
+		} else {
+			sprintf(res_name, "edma_cc%d", j);
+			r[j] = platform_get_resource_byname(pdev,
+						IORESOURCE_MEM,
+						res_name);
+		}
+		if (!r[j]) {
+			if (found)
+				break;
+			else
+				return -ENODEV;
+		} else {
+			found = 1;
+		}
+
+		len[j] = resource_size(r[j]);
+
+		r[j] = request_mem_region(r[j]->start, len[j],
+			dev_name(&pdev->dev));
+		if (!r[j]) {
+			status = -EBUSY;
+			goto fail1;
+		}
+
+		edmacc_regs_base[j] = ioremap(r[j]->start, len[j]);
+		if (!edmacc_regs_base[j]) {
+			status = -EBUSY;
+			goto fail1;
+		}
+
+		edma_cc[j] = kzalloc(sizeof(struct edma), GFP_KERNEL);
+		if (!edma_cc[j]) {
+			status = -ENOMEM;
+			goto fail1;
+		}
+
+		edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel,
+							EDMA_MAX_DMACH);
+		edma_cc[j]->num_slots = min_t(unsigned, info[j]->n_slot,
+							EDMA_MAX_PARAMENTRY);
+		edma_cc[j]->num_cc = min_t(unsigned, info[j]->n_cc,
+							EDMA_MAX_CC);
+
+		edma_cc[j]->default_queue = info[j]->default_queue;
+
+		dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n",
+			edmacc_regs_base[j]);
+
+		for (i = 0; i < edma_cc[j]->num_slots; i++)
+			memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i),
+					&dummy_paramset, PARM_SIZE);
+
+		/* Mark all channels as unused */
+		memset(edma_cc[j]->edma_unused, 0xff,
+			sizeof(edma_cc[j]->edma_unused));
+
+		if (info[j]->rsv) {
+
+			/* Clear the reserved channels in unused list */
+			rsv_chans = info[j]->rsv->rsv_chans;
+			if (rsv_chans) {
+				for (i = 0; rsv_chans[i][0] != -1; i++) {
+					off = rsv_chans[i][0];
+					ln = rsv_chans[i][1];
+					clear_bits(off, ln,
+						edma_cc[j]->edma_unused);
+				}
+			}
+
+			/* Set the reserved slots in inuse list */
+			rsv_slots = info[j]->rsv->rsv_slots;
+			if (rsv_slots) {
+				for (i = 0; rsv_slots[i][0] != -1; i++) {
+					off = rsv_slots[i][0];
+					ln = rsv_slots[i][1];
+					set_bits(off, ln,
+						edma_cc[j]->edma_inuse);
+				}
+			}
+		}
+
+		/* Clear the xbar mapped channels in unused list */
+		xbar_chans = info[j]->xbar_chans;
+		if (xbar_chans) {
+			for (i = 0; xbar_chans[i][1] != -1; i++) {
+				off = xbar_chans[i][1];
+				clear_bits(off, 1,
+					edma_cc[j]->edma_unused);
+			}
+		}
+
+		if (node)
+			irq[j] = irq_of_parse_and_map(node, 0);
+		else {
+			sprintf(irq_name, "edma%d", j);
+			irq[j] = platform_get_irq_byname(pdev, irq_name);
+		}
+		edma_cc[j]->irq_res_start = irq[j];
+		status = request_irq(irq[j], dma_irq_handler, 0, "edma",
+					&pdev->dev);
+		if (status < 0) {
+			dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+				irq[j], status);
+			goto fail;
+		}
+
+		if (node)
+			err_irq[j] = irq_of_parse_and_map(node, 2);
+		else {
+			sprintf(irq_name, "edma%d_err", j);
+			err_irq[j] = platform_get_irq_byname(pdev, irq_name);
+		}
+		edma_cc[j]->irq_res_end = err_irq[j];
+		status = request_irq(err_irq[j], dma_ccerr_handler, 0,
+					"edma_error", &pdev->dev);
+		if (status < 0) {
+			dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+				err_irq[j], status);
+			goto fail;
+		}
+
+		for (i = 0; i < edma_cc[j]->num_channels; i++)
+			map_dmach_queue(j, i, info[j]->default_queue);
+
+		queue_tc_mapping = info[j]->queue_tc_mapping;
+		queue_priority_mapping = info[j]->queue_priority_mapping;
+
+		/* Event queue to TC mapping */
+		for (i = 0; queue_tc_mapping[i][0] != -1; i++)
+			map_queue_tc(j, queue_tc_mapping[i][0],
+					queue_tc_mapping[i][1]);
+
+		/* Event queue priority mapping */
+		for (i = 0; queue_priority_mapping[i][0] != -1; i++)
+			assign_priority_to_queue(j,
+						queue_priority_mapping[i][0],
+						queue_priority_mapping[i][1]);
+
+		/* Map the channel to param entry if channel mapping logic
+		 * exist
+		 */
+		if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST)
+			map_dmach_param(j);
+
+		for (i = 0; i < info[j]->n_region; i++) {
+			edma_write_array2(j, EDMA_DRAE, i, 0, 0x0);
+			edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
+			edma_write_array(j, EDMA_QRAE, i, 0x0);
+		}
+		arch_num_cc++;
+	}
+
+	return 0;
+
+fail:
+	for (i = 0; i < EDMA_MAX_CC; i++) {
+		if (err_irq[i])
+			free_irq(err_irq[i], &pdev->dev);
+		if (irq[i])
+			free_irq(irq[i], &pdev->dev);
+	}
+fail1:
+	for (i = 0; i < EDMA_MAX_CC; i++) {
+		if (r[i])
+			release_mem_region(r[i]->start, len[i]);
+		if (edmacc_regs_base[i])
+			iounmap(edmacc_regs_base[i]);
+		kfree(edma_cc[i]);
+	}
+	return status;
+}
+
+static const struct of_device_id edma_of_ids[] = {
+	{ .compatible = "ti,edma3", },
+	{}
+};
+
+static struct platform_driver edma_driver = {
+	.driver = {
+		.name	= "edma",
+		.of_match_table = edma_of_ids,
+	},
+	.probe = edma_probe,
+};
+
+static int __init edma_init(void)
+{
+	return platform_driver_probe(&edma_driver, edma_probe);
+}
+arch_initcall(edma_init);
+
diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig
index f292239..571445f 100644
--- a/arch/arm/configs/da8xx_omapl_defconfig
+++ b/arch/arm/configs/da8xx_omapl_defconfig
@@ -1,132 +1,1965 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 3.7.0-rc1 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_NEED_MACH_GPIO_H=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_HAVE_IRQ_WORK=y
+
+#
+# General setup
+#
 CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_FHANDLE is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_IRQ_DOMAIN=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+CONFIG_KTIME_SCALAR=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_PREEMPT_RCU=y
+CONFIG_PREEMPT_RCU=y
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_BOOST is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EXPERT=y
+CONFIG_HAVE_UID16=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_GENERIC_KERNEL_THREAD=y
+CONFIG_GENERIC_KERNEL_EXECVE=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM2835 is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MXS is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_PLAT_SPEAR is not set
 CONFIG_ARCH_DAVINCI=y
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VT8500 is not set
+# CONFIG_ARCH_ZYNQ is not set
+CONFIG_CP_INTC=y
+
+#
+# TI DaVinci Implementations
+#
+
+#
+# DaVinci Core Type
+#
+# CONFIG_ARCH_DAVINCI_DM644x is not set
+# CONFIG_ARCH_DAVINCI_DM355 is not set
+# CONFIG_ARCH_DAVINCI_DM646x is not set
 CONFIG_ARCH_DAVINCI_DA830=y
 CONFIG_ARCH_DAVINCI_DA850=y
-CONFIG_MACH_DA8XX_DT=y
+CONFIG_ARCH_DAVINCI_DA8XX=y
+# CONFIG_ARCH_DAVINCI_DM365 is not set
+# CONFIG_ARCH_DAVINCI_TNETV107X is not set
+
+#
+# DaVinci Board Type
+#
+CONFIG_MACH_DAVINCI_DA830_EVM=y
+CONFIG_DA830_UI_LCD=y
+# CONFIG_DA830_UI_NAND is not set
+CONFIG_MACH_DAVINCI_DA850_EVM=y
+CONFIG_DA850_UI_NONE=y
+# CONFIG_DA850_UI_RMII is not set
+# CONFIG_DA850_UI_SD_VIDEO_PORT is not set
+# CONFIG_DA850_WL12XX is not set
+CONFIG_GPIO_PCA953X=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
 CONFIG_MACH_MITYOMAPL138=y
 CONFIG_MACH_OMAPL138_HAWKBOARD=y
+CONFIG_DAVINCI_MUX=y
+# CONFIG_DAVINCI_MUX_DEBUG is not set
+# CONFIG_DAVINCI_MUX_WARNINGS is not set
 CONFIG_DAVINCI_RESET_CLOCKS=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_USE_DOMAINS=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+CONFIG_CPU_DCACHE_WRITETHROUGH=y
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_NR_BANKS=8
+CONFIG_TI_PRIV_EDMA=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
+CONFIG_PREEMPT_COUNT=y
+CONFIG_HZ=100
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
-CONFIG_LEDS=y
-CONFIG_USE_OF=y
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+
+#
+# Boot options
+#
+# CONFIG_USE_OF is not set
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_AUTO_ZRELADDR is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
 CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
 CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=m
 CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# ARM CPU frequency scaling drivers
+#
+# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set
+# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set
+# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set
 CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_CLK=y
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
 CONFIG_NET=y
+
+#
+# Networking options
+#
 CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
 CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
 CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 # CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_GRE is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
 CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV6 is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_RFKILL_REGULATOR is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+CONFIG_HAVE_BPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
+# CONFIG_DMA_SHARED_BUFFER is not set
+# CONFIG_CMA is not set
+
+#
+# Bus devices
+#
+# CONFIG_OMAP_OCP2SCP is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLKDEVS is not set
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+CONFIG_M25PXX_USE_FAST_READ=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+# CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=1
 CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_ATMEL_PWM is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_BMP085_I2C is not set
+# CONFIG_BMP085_SPI is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
 CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=m
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
 CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
 CONFIG_NETDEVICES=y
-CONFIG_TUN=m
-CONFIG_LXT_PHY=y
-CONFIG_LSI_ET1011C_PHY=y
-CONFIG_NET_ETHERNET=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
 CONFIG_MII=y
-CONFIG_TI_DAVINCI_EMAC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
 CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
 CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+
+#
+# CAIF transport drivers
+#
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+CONFIG_NET_VENDOR_CHELSIO=y
+CONFIG_NET_VENDOR_CIRRUS=y
+# CONFIG_CS89x0 is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_FARADAY=y
+# CONFIG_FTMAC100 is not set
+# CONFIG_FTGMAC100 is not set
+CONFIG_NET_VENDOR_INTEL=y
+CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_MARVELL=y
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_AX88796 is not set
+# CONFIG_ETHOC is not set
+CONFIG_NET_VENDOR_SEEQ=y
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_VENDOR_SMSC=y
+# CONFIG_SMC91X is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_TI=y
+CONFIG_TI_DAVINCI_EMAC=y
+CONFIG_TI_DAVINCI_MDIO=y
+CONFIG_TI_DAVINCI_CPDMA=y
+# CONFIG_TI_CPSW is not set
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+CONFIG_LXT_PHY=y
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+CONFIG_LSI_ET1011C_PHY=y
+# CONFIG_MICREL_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_WLAN=y
+# CONFIG_HOSTAP is not set
+# CONFIG_WL_TI is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_POLLDEV=y
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
 CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
 CONFIG_INPUT_EVDEV=m
 CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
 CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
 CONFIG_KEYBOARD_GPIO=y
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
 CONFIG_KEYBOARD_XTKBD=m
 # CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
+# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
+# CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_EGALAX is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_ILI210X is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_WACOM_I2C is not set
+# CONFIG_TOUCHSCREEN_MAX11801 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MMS114 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_PIXCIR is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_TOUCHSCREEN_ST1232 is not set
+# CONFIG_TOUCHSCREEN_TPS6507X is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
 CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
 # CONFIG_VT_CONSOLE is not set
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=3
-CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_EM is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_HW_RANDOM_ATMEL is not set
+# CONFIG_HW_RANDOM_EXYNOS is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
 CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
 CONFIG_I2C_DAVINCI=y
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_DAVINCI=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+
+#
+# Enable Device Drivers -> PPS to see the PTP clock options.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_EM is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X_IRQ is not set
+CONFIG_GPIO_PCF857X=y
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_74X164 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_POWER_AVS is not set
 # CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
 CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_DAVINCI_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_PALMAS is not set
 CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
 CONFIG_REGULATOR_DUMMY=y
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_GPIO is not set
+# CONFIG_REGULATOR_AD5398 is not set
+# CONFIG_REGULATOR_FAN53555 is not set
+# CONFIG_REGULATOR_ISL6271A is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8649 is not set
+# CONFIG_REGULATOR_MAX8660 is not set
+# CONFIG_REGULATOR_MAX8952 is not set
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_LP3972 is not set
+# CONFIG_REGULATOR_LP872X is not set
+# CONFIG_REGULATOR_TPS62360 is not set
+# CONFIG_REGULATOR_TPS65023 is not set
 CONFIG_REGULATOR_TPS6507X=y
+# CONFIG_REGULATOR_TPS6524X is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
 CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_CFB_REV_PIXELS_IN_BYTE=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_WMT_GE_ROPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
 CONFIG_FB_DA8XX=y
-# CONFIG_VGA_CONSOLE is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_ST7735 is not set
+# CONFIG_EXYNOS_VIDEO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
 CONFIG_LOGO=y
-CONFIG_SOUND=m
-CONFIG_SND=m
-CONFIG_SND_SOC=m
-CONFIG_SND_DAVINCI_SOC=m
-# CONFIG_HID_SUPPORT is not set
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_COMPRESS_OFFLOAD=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_ALOOP is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+CONFIG_SND_SOC=y
+CONFIG_SND_DAVINCI_SOC=y
+CONFIG_SND_DAVINCI_SOC_MCASP=y
+# CONFIG_SND_DA830_SOC_EVM is not set
+CONFIG_SND_DA850_SOC_EVM=y
+# CONFIG_SND_DESIGNWARE_I2S is not set
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TLV320AIC3X=y
+# CONFIG_SND_SIMPLE_CARD is not set
+# CONFIG_SOUND_PRIME is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB_ARCH_HAS_XHCI is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SDHCI_PXAV3 is not set
+# CONFIG_MMC_SDHCI_PXAV2 is not set
+CONFIG_MMC_DAVINCI=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_OMAP=y
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+# CONFIG_DW_DMAC is not set
+# CONFIG_TIMB_DMA is not set
+CONFIG_TI_EDMA=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+
+#
+# DMA Clients
+#
+# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+# CONFIG_UIO_PDRV is not set
+# CONFIG_UIO_PDRV_GENIRQ is not set
+CONFIG_UIO_PRUSS=y
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+CONFIG_CLKDEV_LOOKUP=y
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_IOMMU_SUPPORT=y
+
+#
+# Remoteproc drivers (EXPERIMENTAL)
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers (EXPERIMENTAL)
+#
+# CONFIG_VIRT_DRIVERS is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+
+#
+# File systems
+#
 CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
 CONFIG_XFS_FS=m
-CONFIG_INOTIFY=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_EXPORTFS=m
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
 CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_LOGFS is not set
 CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
 CONFIG_MINIX_FS=m
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
-CONFIG_SMB_FS=m
-CONFIG_PARTITION_ADVANCED=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
 CONFIG_NLS_ASCII=m
 CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
 CONFIG_NLS_UTF8=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
 CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+CONFIG_DEBUG_PREEMPT=y
 CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_PROVE_RCU_DELAY is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_LKDTM is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_USER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA1_ARM is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_AES_ARM is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
 # CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
 CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
 CONFIG_CRC_T10DIF=m
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+# CONFIG_AVERAGE is not set
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index 82ce8d7..d322dec 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -1,250 +1,2840 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 3.8.0-rc2 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
 CONFIG_EXPERIMENTAL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_FHANDLE is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_IRQ_DOMAIN=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+CONFIG_SPARSE_IRQ=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
 CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_RCU_FANOUT=32
+CONFIG_RCU_FANOUT_LEAF=16
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_RCU_FAST_NO_HZ is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_NOCB_CPU is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EXPERT=y
+CONFIG_HAVE_UID16=y
+CONFIG_UID16=y
 # CONFIG_SYSCTL_SYSCALL is not set
-CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
 CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
 CONFIG_KPROBES=y
+# CONFIG_JUMP_LABEL is not set
+CONFIG_KRETPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_CLONE_BACKWARDS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_MODULE_SIG is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM2835 is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXS is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_DAVINCI is not set
 CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VT8500_SINGLE is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+
+#
+# TI OMAP Common Features
+#
+# CONFIG_ARCH_OMAP1 is not set
+CONFIG_ARCH_OMAP2PLUS=y
+
+#
+# OMAP Feature Selections
+#
+CONFIG_OMAP_DEBUG_DEVICES=y
 CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_MUX=y
 CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_32K_TIMER=y
+# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_PM_NOOP=y
+CONFIG_MACH_OMAP_GENERIC=y
+
+#
+# TI OMAP2/3/4 Specific Features
+#
+CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
+CONFIG_SOC_HAS_OMAP2_SDRC=y
+CONFIG_SOC_HAS_REALTIME_COUNTER=y
+CONFIG_ARCH_OMAP2=y
+CONFIG_ARCH_OMAP3=y
+CONFIG_ARCH_OMAP4=y
+CONFIG_SOC_OMAP5=y
+
+#
+# OMAP Core Type
+#
+CONFIG_SOC_OMAP2420=y
+CONFIG_SOC_OMAP2430=y
+CONFIG_SOC_OMAP3430=y
+CONFIG_SOC_TI81XX=y
+CONFIG_SOC_AM33XX=y
+CONFIG_OMAP_PACKAGE_ZAF=y
+CONFIG_OMAP_PACKAGE_ZAC=y
+CONFIG_OMAP_PACKAGE_CBB=y
+CONFIG_OMAP_PACKAGE_CUS=y
+CONFIG_OMAP_PACKAGE_CBP=y
+CONFIG_OMAP_PACKAGE_CBL=y
+CONFIG_OMAP_PACKAGE_CBS=y
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP2_TUSB6010=y
+CONFIG_MACH_OMAP_H4=y
+CONFIG_MACH_OMAP_APOLLON=y
+CONFIG_MACH_OMAP_2430SDP=y
+CONFIG_MACH_OMAP3_BEAGLE=y
+CONFIG_MACH_DEVKIT8000=y
+CONFIG_MACH_OMAP_LDP=y
+CONFIG_MACH_OMAP3530_LV_SOM=y
+CONFIG_MACH_OMAP3_TORPEDO=y
+CONFIG_MACH_OVERO=y
+CONFIG_MACH_OMAP3EVM=y
+CONFIG_MACH_OMAP3517EVM=y
+# CONFIG_MACH_CRANEBOARD is not set
+CONFIG_MACH_OMAP3_PANDORA=y
+CONFIG_MACH_TOUCHBOOK=y
+CONFIG_MACH_OMAP_3430SDP=y
+CONFIG_MACH_NOKIA_N800=y
+CONFIG_MACH_NOKIA_N810=y
+CONFIG_MACH_NOKIA_N810_WIMAX=y
+CONFIG_MACH_NOKIA_N8X0=y
+CONFIG_MACH_NOKIA_RM680=y
+CONFIG_MACH_NOKIA_RX51=y
+CONFIG_MACH_OMAP_ZOOM2=y
+CONFIG_MACH_OMAP_ZOOM3=y
+CONFIG_MACH_CM_T35=y
+CONFIG_MACH_CM_T3517=y
+CONFIG_MACH_CM_T3730=y
+CONFIG_MACH_IGEP0020=y
+CONFIG_MACH_IGEP0030=y
+CONFIG_MACH_SBC3530=y
+CONFIG_MACH_OMAP_3630SDP=y
+CONFIG_MACH_TI8168EVM=y
+CONFIG_MACH_TI8148EVM=y
+CONFIG_MACH_OMAP_4430SDP=y
+CONFIG_MACH_OMAP4_PANDA=y
+# CONFIG_OMAP3_EMU is not set
+# CONFIG_OMAP3_SDRC_AC_TIMING is not set
+# CONFIG_OMAP4_ERRATA_I688 is not set
+# CONFIG_ARCH_VT8500 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_USE_DOMAINS=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
 CONFIG_ARM_THUMBEE=y
+# CONFIG_ARM_VIRT_EXT is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_OUTER_CACHE=y
+CONFIG_OUTER_CACHE_SYNC=y
+CONFIG_CACHE_L2X0=y
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+CONFIG_ARM_NR_BANKS=8
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_326103 is not set
 CONFIG_ARM_ERRATA_411920=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+# CONFIG_ARM_ERRATA_742230 is not set
+# CONFIG_ARM_ERRATA_742231 is not set
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_PL310_ERRATA_727915=y
+# CONFIG_ARM_ERRATA_743622 is not set
+# CONFIG_ARM_ERRATA_751472 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_754327 is not set
+# CONFIG_ARM_ERRATA_764369 is not set
+# CONFIG_PL310_ERRATA_769419 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+CONFIG_ARM_GIC=y
+CONFIG_TI_PRIV_EDMA=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
 CONFIG_SMP=y
+CONFIG_SMP_ON_UP=y
+CONFIG_ARM_CPU_TOPOLOGY=y
+# CONFIG_SCHED_MC is not set
+# CONFIG_SCHED_SMT is not set
+CONFIG_HAVE_ARM_SCU=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_HAVE_ARM_TWD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
 CONFIG_NR_CPUS=2
-CONFIG_LEDS=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_LOCAL_TIMERS=y
+CONFIG_ARCH_NR_GPIO=512
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HIGHMEM=y
+# CONFIG_HIGHPTE is not set
+CONFIG_HW_PERF_EVENTS=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_FRONTSWAP is not set
+CONFIG_FORCE_MAX_ZONEORDER=12
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_ARM_APPENDED_DTB is not set
 CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
+CONFIG_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_CMDLINE_EXTEND is not set
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
 CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_AUTO_ZRELADDR is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
 CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
 CONFIG_BINFMT_MISC=y
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_PM=y
 CONFIG_PM_DEBUG=y
+# CONFIG_PM_ADVANCED_DEBUG is not set
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_PM_SLEEP_DEBUG=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_HAS_OPP=y
+CONFIG_PM_OPP=y
+CONFIG_PM_CLK=y
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
 CONFIG_NET=y
+
+#
+# Networking options
+#
 CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
 CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
 CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
 CONFIG_NET_KEY=y
 CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
 # CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
 CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
 CONFIG_BT=m
+# CONFIG_BT_RFCOMM is not set
+# CONFIG_BT_BNEP is not set
+# CONFIG_BT_HIDP is not set
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
 CONFIG_BT_HCIUART=m
 CONFIG_BT_HCIUART_H4=y
 CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIUART_ATH3K is not set
 CONFIG_BT_HCIUART_LL=y
+# CONFIG_BT_HCIUART_3WIRE is not set
 CONFIG_BT_HCIBCM203X=m
 CONFIG_BT_HCIBPA10X=m
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
 CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+# CONFIG_CFG80211_WEXT is not set
+CONFIG_LIB80211=m
+# CONFIG_LIB80211_DEBUG is not set
 CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
 CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
 CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_RFKILL_REGULATOR is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+CONFIG_HAVE_BPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_CONNECTOR=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=m
+CONFIG_REGMAP_IRQ=y
+# CONFIG_DMA_SHARED_BUFFER is not set
+# CONFIG_CMA is not set
+
+#
+# Bus devices
+#
+# CONFIG_OMAP_OCP2SCP is not set
+CONFIG_OMAP_INTERCONNECT=y
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
 CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
 CONFIG_MTD_OOPS=y
+# CONFIG_MTD_SWAP is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
 CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
 CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PHYSMAP_OF is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+CONFIG_M25PXX_USE_FAST_READ=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
 CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_DENALI is not set
+# CONFIG_MTD_NAND_GPIO is not set
 CONFIG_MTD_NAND_OMAP2=y
+# CONFIG_MTD_NAND_OMAP_BCH is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
 CONFIG_MTD_ONENAND=y
 CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
 CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
 CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+
+#
+# Device Tree and Open Firmware support
+#
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_OF_SELFTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_MTD=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_ATMEL_PWM is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_BMP085_I2C is not set
+# CONFIG_BMP085_SPI is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+CONFIG_GPEVT=y
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+CONFIG_EEPROM_93CX6=y
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
 CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
 CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
 CONFIG_SCSI_SCAN_ASYNC=y
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
 CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_BLK_DEV_DM is not set
+# CONFIG_TARGET_CORE is not set
 CONFIG_NETDEVICES=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-CONFIG_SMSC911X=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_MII=y
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6060 is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+# CONFIG_NET_DSA_MV88E6131 is not set
+# CONFIG_NET_DSA_MV88E6123_61_65 is not set
+CONFIG_ETHERNET=y
+CONFIG_NET_CADENCE=y
+# CONFIG_ARM_AT91_ETHER is not set
+# CONFIG_MACB is not set
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+CONFIG_NET_VENDOR_CIRRUS=y
+# CONFIG_CS89x0 is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_FARADAY=y
+# CONFIG_FTMAC100 is not set
+# CONFIG_FTGMAC100 is not set
+CONFIG_NET_VENDOR_INTEL=y
+CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_MARVELL=y
+# CONFIG_MVMDIO is not set
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8842 is not set
 CONFIG_KS8851=y
 CONFIG_KS8851_MLL=y
-CONFIG_LIBERTAS=m
-CONFIG_LIBERTAS_USB=m
-CONFIG_LIBERTAS_SDIO=m
-CONFIG_LIBERTAS_DEBUG=y
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_AX88796 is not set
+# CONFIG_ETHOC is not set
+CONFIG_NET_VENDOR_SEEQ=y
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_VENDOR_SMSC=y
+CONFIG_SMC91X=y
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
+# CONFIG_SMSC911X_ARCH_HOOKS is not set
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_TI=y
+# CONFIG_TI_DAVINCI_EMAC is not set
+CONFIG_TI_DAVINCI_MDIO=y
+CONFIG_TI_DAVINCI_CPDMA=y
+CONFIG_TI_CPSW=y
+# CONFIG_TI_CPTS is not set
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AT803X_PHY is not set
+# CONFIG_AMD_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
 CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
+CONFIG_USB_NET_CDC_NCM=y
+# CONFIG_USB_NET_CDC_MBIM is not set
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_SMSC75XX is not set
 CONFIG_USB_NET_SMSC95XX=y
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=y
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_CDC_SUBSET=y
 CONFIG_USB_ALI_M5632=y
 CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
 CONFIG_USB_EPSON2888=y
 CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_NET_CX82310_ETH is not set
+# CONFIG_USB_NET_KALMIA is not set
+# CONFIG_USB_NET_QMI_WWAN is not set
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_USB_SIERRA_NET is not set
+# CONFIG_USB_VL600 is not set
+CONFIG_WLAN=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AT76C50X_USB is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_ATH_CARDS is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_BRCMFMAC is not set
+# CONFIG_HOSTAP is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+# CONFIG_LIBERTAS_SPI is not set
+CONFIG_LIBERTAS_DEBUG=y
+# CONFIG_LIBERTAS_MESH is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_RTL8192CU is not set
+# CONFIG_WL_TI is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_MWIFIEX is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+CONFIG_INPUT_MATRIXKMAP=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 CONFIG_INPUT_JOYDEV=y
 CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
 CONFIG_KEYBOARD_GPIO=y
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
 CONFIG_KEYBOARD_TWL4030=y
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
+# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
+# CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_EGALAX is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_ILI210X is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_WACOM_I2C is not set
+# CONFIG_TOUCHSCREEN_MAX11801 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MMS114 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_PIXCIR is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_TOUCHSCREEN_ST1232 is not set
+# CONFIG_TOUCHSCREEN_TPS6507X is not set
 CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
 CONFIG_INPUT_TWL4030_PWRBUTTON=y
+# CONFIG_INPUT_TWL4030_VIBRA is not set
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
 CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
+# CONFIG_SERIAL_8250_DW is not set
+# CONFIG_SERIAL_8250_EM is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_SERIAL_OMAP=y
+CONFIG_SERIAL_OMAP_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
 CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_HW_RANDOM_ATMEL is not set
+CONFIG_HW_RANDOM_OMAP=y
+# CONFIG_HW_RANDOM_EXYNOS is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
 CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
 CONFIG_SPI_OMAP24XX=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+# CONFIG_PTP_1588_CLOCK_PCH is not set
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+CONFIG_DEBUG_PINCTRL=y
 CONFIG_PINCTRL_SINGLE=y
+# CONFIG_PINCTRL_EXYNOS4 is not set
+# CONFIG_PINCTRL_EXYNOS5440 is not set
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_TS5500 is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
 CONFIG_GPIO_TWL4030=y
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_74X164 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+# CONFIG_GPIO_TPS65910 is not set
+
+#
+# USB GPIO expanders:
+#
 CONFIG_W1=y
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+# CONFIG_W1_MASTER_DS1WM is not set
+# CONFIG_W1_MASTER_GPIO is not set
+# CONFIG_HDQ_MASTER_OMAP is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2408 is not set
+# CONFIG_W1_SLAVE_DS2423 is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+# CONFIG_W1_SLAVE_DS2780 is not set
+# CONFIG_W1_SLAVE_DS2781 is not set
+# CONFIG_W1_SLAVE_DS28E04 is not set
+# CONFIG_W1_SLAVE_BQ27000 is not set
 CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_TWL4030 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_MANAGER is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7314 is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7410 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_GPIO_FAN is not set
+# CONFIG_SENSORS_HIH6130 is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_LM95245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX1668 is not set
+# CONFIG_SENSORS_MAX197 is not set
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_MCP3021 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_PMBUS is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SHT21 is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SCH56XX_COMMON is not set
+# CONFIG_SENSORS_SCH5627 is not set
+# CONFIG_SENSORS_SCH5636 is not set
+# CONFIG_SENSORS_ADS1015 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_ADS7871 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_INA2XX is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP102 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_THERMAL is not set
 CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_CORE=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MPCORE_WATCHDOG is not set
 CONFIG_OMAP_WATCHDOG=y
 CONFIG_TWL4030_WATCHDOG=y
+# CONFIG_MAX63XX_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
 CONFIG_MFD_TPS65217=y
-CONFIG_REGULATOR_TWL4030=y
+# CONFIG_MFD_TPS6586X is not set
+CONFIG_MFD_TPS65910=y
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+CONFIG_MENELAUS=y
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_MADC is not set
+CONFIG_TWL4030_POWER=y
+CONFIG_MFD_TWL4030_AUDIO=y
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_AS3711 is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_DUMMY is not set
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_GPIO is not set
+# CONFIG_REGULATOR_AD5398 is not set
+# CONFIG_REGULATOR_FAN53555 is not set
+# CONFIG_REGULATOR_ISL6271A is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8649 is not set
+# CONFIG_REGULATOR_MAX8660 is not set
+# CONFIG_REGULATOR_MAX8952 is not set
+# CONFIG_REGULATOR_MAX8973 is not set
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_LP3972 is not set
+# CONFIG_REGULATOR_LP872X is not set
+# CONFIG_REGULATOR_TPS51632 is not set
+# CONFIG_REGULATOR_TPS62360 is not set
 CONFIG_REGULATOR_TPS65023=y
 CONFIG_REGULATOR_TPS6507X=y
 CONFIG_REGULATOR_TPS65217=y
+# CONFIG_REGULATOR_TPS6524X is not set
+CONFIG_REGULATOR_TPS65910=y
+CONFIG_REGULATOR_TWL4030=y
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
 CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=y
+# CONFIG_FB_WMT_GE_ROPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
-CONFIG_FB_OMAP_LCD_VGA=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_TMIO is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+CONFIG_FB_ST7735=y
+CONFIG_OMAP2_VRFB=y
 CONFIG_OMAP2_DSS=m
+# CONFIG_OMAP2_DSS_DEBUG is not set
+# CONFIG_OMAP2_DSS_DEBUGFS is not set
+CONFIG_OMAP2_DSS_DPI=y
 CONFIG_OMAP2_DSS_RFBI=y
+CONFIG_OMAP2_DSS_VENC=y
+CONFIG_OMAP4_DSS_HDMI=y
 CONFIG_OMAP2_DSS_SDI=y
 CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y
 CONFIG_FB_OMAP2=m
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+CONFIG_FB_OMAP2_NUM_FBS=3
+
+#
+# OMAP2/3 Display Device Drivers
+#
 CONFIG_PANEL_GENERIC_DPI=m
+# CONFIG_PANEL_TFP410 is not set
+# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set
 CONFIG_PANEL_SHARP_LS037V7DW01=m
 CONFIG_PANEL_NEC_NL8048HL11_01B=m
+# CONFIG_PANEL_PICODLP is not set
 CONFIG_PANEL_TAAL=m
 CONFIG_PANEL_TPO_TD043MTEA1=m
 CONFIG_PANEL_ACX565AKM=m
+# CONFIG_PANEL_N8X0 is not set
+# CONFIG_EXYNOS_VIDEO is not set
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_L4F00242T03 is not set
+# CONFIG_LCD_LMS283GF05 is not set
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
 CONFIG_LCD_PLATFORM=y
-CONFIG_DISPLAY_SUPPORT=y
+# CONFIG_LCD_S6E63M0 is not set
+# CONFIG_LCD_LD9040 is not set
+# CONFIG_LCD_AMS369FG06 is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_GENERIC=m
+# CONFIG_BACKLIGHT_ADP8860 is not set
+# CONFIG_BACKLIGHT_ADP8870 is not set
+# CONFIG_BACKLIGHT_LM3630 is not set
+# CONFIG_BACKLIGHT_LM3639 is not set
+# CONFIG_BACKLIGHT_LP855X is not set
+# CONFIG_BACKLIGHT_PANDORA is not set
+# CONFIG_BACKLIGHT_TPS65217 is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_FONTS=y
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
 CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_FB_SSD1307 is not set
 CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
 CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_COMPRESS_OFFLOAD=m
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
 CONFIG_SND_VERBOSE_PRINTK=y
 CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_ALOOP is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
 CONFIG_SND_USB_AUDIO=m
+# CONFIG_SND_USB_UA101 is not set
+# CONFIG_SND_USB_CAIAQ is not set
+# CONFIG_SND_USB_6FIRE is not set
 CONFIG_SND_SOC=m
+CONFIG_SND_SOC_DMAENGINE_PCM=y
+# CONFIG_SND_DESIGNWARE_I2S is not set
 CONFIG_SND_OMAP_SOC=m
+CONFIG_SND_OMAP_SOC_MCBSP=m
+# CONFIG_SND_OMAP_SOC_N810 is not set
+# CONFIG_SND_OMAP_SOC_RX51 is not set
+# CONFIG_SND_OMAP_SOC_AM3517EVM is not set
+# CONFIG_SND_OMAP_SOC_SDP3430 is not set
 CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m
+# CONFIG_SND_OMAP_SOC_OMAP_HDMI is not set
 CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
+# CONFIG_SND_OMAP_SOC_ZOOM2 is not set
+CONFIG_SND_SOC_I2C_AND_SPI=m
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=m
+# CONFIG_SND_SIMPLE_CARD is not set
+# CONFIG_SOUND_PRIME is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO_TPKBD is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB_ARCH_HAS_XHCI is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DYNAMIC_MINORS is not set
 CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_DWC3 is not set
 CONFIG_USB_MON=y
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_RENESAS_USBHS is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
 CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
 CONFIG_USB_STORAGE=y
-CONFIG_USB_LIBUSUAL=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 CONFIG_USB_TEST=y
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_OMAP_USB2 is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_RCAR_PHY is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+
+#
+# USB Peripheral Controller
+#
+# CONFIG_USB_FUSB300 is not set
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_MV_UDC is not set
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_LIBCOMPOSITE=m
 CONFIG_USB_ZERO=m
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_G_NCM is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FUNCTIONFS is not set
+# CONFIG_USB_MASS_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_ACM_MS is not set
+# CONFIG_USB_G_MULTI is not set
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_DBGP is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_NOP_USB_XCEIV is not set
 CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
 CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
 CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SDHCI_PXAV3 is not set
+# CONFIG_MMC_SDHCI_PXAV2 is not set
 CONFIG_MMC_OMAP=y
 CONFIG_MMC_OMAP_HS=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
 CONFIG_RTC_DRV_TWL92330=y
 CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_TPS65910 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_OMAP is not set
+# CONFIG_RTC_DRV_SNVS is not set
 CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+# CONFIG_DW_DMAC is not set
+# CONFIG_TIMB_DMA is not set
+CONFIG_TI_EDMA=y
 CONFIG_DMA_OMAP=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+
+#
+# DMA Clients
+#
+# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_DEBUG is not set
+
+#
+# Hardware Spinlock drivers
+#
+# CONFIG_HWSPINLOCK_OMAP is not set
+CONFIG_CLKSRC_MMIO=y
+CONFIG_IOMMU_SUPPORT=y
+CONFIG_OF_IOMMU=y
+# CONFIG_OMAP_IOMMU is not set
+
+#
+# Remoteproc drivers (EXPERIMENTAL)
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers (EXPERIMENTAL)
+#
+# CONFIG_VIRT_DRIVERS is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+# CONFIG_IPACK_BUS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
 CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
 CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
 CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
 CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
 CONFIG_JFFS2_SUMMARY=y
 CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
 CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
 CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
 CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_LOGFS is not set
 CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
 CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
+# CONFIG_NFS_SWAP is not set
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
 CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
 CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHED_DEBUG=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
 CONFIG_PROVE_LOCKING=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+CONFIG_LOCKDEP=y
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_LOCKDEP is not set
+CONFIG_TRACE_IRQFLAGS=y
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_DEBUG_INFO_REDUCED is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=21
+# CONFIG_RCU_CPU_STALL_INFO is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_LKDTM is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACE_CLOCK=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_EVENT_POWER_TRACING_DEPRECATED=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_KPROBE_EVENT=y
+CONFIG_PROBE_EVENTS=y
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_ARM_KPROBES_TEST is not set
+# CONFIG_PID_IN_CONTEXTIDR is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
 CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_SMACK is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_SECURITY_YAMA is not set
+# CONFIG_IMA is not set
+# CONFIG_EVM is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_PCRYPT is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
 CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA1_ARM is not set
+CONFIG_CRYPTO_SHA256=m
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_AES_ARM is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_OMAP_SHAM is not set
+# CONFIG_CRYPTO_DEV_OMAP_AES is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_PERCPU_RWSEM=y
 CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
 CONFIG_CRC_T10DIF=y
 CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
 CONFIG_CRC7=y
 CONFIG_LIBCRC32C=y
-CONFIG_SOC_OMAP5=y
-CONFIG_TI_DAVINCI_MDIO=y
-CONFIG_TI_DAVINCI_CPDMA=y
-CONFIG_TI_CPSW=y
+# CONFIG_CRC8 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_AVERAGE=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 3f6cbb2..4540dad 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -931,3 +931,12 @@ const struct seq_operations cpuinfo_op = {
 	.stop	= c_stop,
 	.show	= c_show
 };
+
+/* export the cache management functions */
+#ifndef MULTI_CACHE
+
+EXPORT_SYMBOL(__glue(_CACHE,_dma_map_area));
+EXPORT_SYMBOL(__glue(_CACHE,_dma_unmap_area));
+EXPORT_SYMBOL(__glue(_CACHE,_dma_flush_range));
+
+#endif
diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S
index 650d592..94b0650 100644
--- a/arch/arm/lib/memset.S
+++ b/arch/arm/lib/memset.S
@@ -14,27 +14,15 @@
 
 	.text
 	.align	5
-	.word	0
-
-1:	subs	r2, r2, #4		@ 1 do we have enough
-	blt	5f			@ 1 bytes to align with?
-	cmp	r3, #2			@ 1
-	strltb	r1, [r0], #1		@ 1
-	strleb	r1, [r0], #1		@ 1
-	strb	r1, [r0], #1		@ 1
-	add	r2, r2, r3		@ 1 (r2 = r2 - (4 - r3))
-/*
- * The pointer is now aligned and the length is adjusted.  Try doing the
- * memset again.
- */
 
 ENTRY(memset)
 	ands	r3, r0, #3		@ 1 unaligned?
-	bne	1b			@ 1
+	mov	ip, r0			@ preserve r0 as return value
+	bne	6f			@ 1
 /*
- * we know that the pointer in r0 is aligned to a word boundary.
+ * we know that the pointer in ip is aligned to a word boundary.
  */
-	orr	r1, r1, r1, lsl #8
+1:	orr	r1, r1, r1, lsl #8
 	orr	r1, r1, r1, lsl #16
 	mov	r3, r1
 	cmp	r2, #16
@@ -43,29 +31,28 @@ ENTRY(memset)
 #if ! CALGN(1)+0
 
 /*
- * We need an extra register for this loop - save the return address and
- * use the LR
+ * We need 2 extra registers for this loop - use r8 and the LR
  */
-	str	lr, [sp, #-4]!
-	mov	ip, r1
+	stmfd	sp!, {r8, lr}
+	mov	r8, r1
 	mov	lr, r1
 
 2:	subs	r2, r2, #64
-	stmgeia	r0!, {r1, r3, ip, lr}	@ 64 bytes at a time.
-	stmgeia	r0!, {r1, r3, ip, lr}
-	stmgeia	r0!, {r1, r3, ip, lr}
-	stmgeia	r0!, {r1, r3, ip, lr}
+	stmgeia	ip!, {r1, r3, r8, lr}	@ 64 bytes at a time.
+	stmgeia	ip!, {r1, r3, r8, lr}
+	stmgeia	ip!, {r1, r3, r8, lr}
+	stmgeia	ip!, {r1, r3, r8, lr}
 	bgt	2b
-	ldmeqfd	sp!, {pc}		@ Now <64 bytes to go.
+	ldmeqfd	sp!, {r8, pc}		@ Now <64 bytes to go.
 /*
  * No need to correct the count; we're only testing bits from now on
  */
 	tst	r2, #32
-	stmneia	r0!, {r1, r3, ip, lr}
-	stmneia	r0!, {r1, r3, ip, lr}
+	stmneia	ip!, {r1, r3, r8, lr}
+	stmneia	ip!, {r1, r3, r8, lr}
 	tst	r2, #16
-	stmneia	r0!, {r1, r3, ip, lr}
-	ldr	lr, [sp], #4
+	stmneia	ip!, {r1, r3, r8, lr}
+	ldmfd	sp!, {r8, lr}
 
 #else
 
@@ -74,54 +61,63 @@ ENTRY(memset)
  * whole cache lines at once.
  */
 
-	stmfd	sp!, {r4-r7, lr}
+	stmfd	sp!, {r4-r8, lr}
 	mov	r4, r1
 	mov	r5, r1
 	mov	r6, r1
 	mov	r7, r1
-	mov	ip, r1
+	mov	r8, r1
 	mov	lr, r1
 
 	cmp	r2, #96
-	tstgt	r0, #31
+	tstgt	ip, #31
 	ble	3f
 
-	and	ip, r0, #31
-	rsb	ip, ip, #32
-	sub	r2, r2, ip
-	movs	ip, ip, lsl #(32 - 4)
-	stmcsia	r0!, {r4, r5, r6, r7}
-	stmmiia	r0!, {r4, r5}
-	tst	ip, #(1 << 30)
-	mov	ip, r1
-	strne	r1, [r0], #4
+	and	r8, ip, #31
+	rsb	r8, r8, #32
+	sub	r2, r2, r8
+	movs	r8, r8, lsl #(32 - 4)
+	stmcsia	ip!, {r4, r5, r6, r7}
+	stmmiia	ip!, {r4, r5}
+	tst	r8, #(1 << 30)
+	mov	r8, r1
+	strne	r1, [ip], #4
 
 3:	subs	r2, r2, #64
-	stmgeia	r0!, {r1, r3-r7, ip, lr}
-	stmgeia	r0!, {r1, r3-r7, ip, lr}
+	stmgeia	ip!, {r1, r3-r8, lr}
+	stmgeia	ip!, {r1, r3-r8, lr}
 	bgt	3b
-	ldmeqfd	sp!, {r4-r7, pc}
+	ldmeqfd	sp!, {r4-r8, pc}
 
 	tst	r2, #32
-	stmneia	r0!, {r1, r3-r7, ip, lr}
+	stmneia	ip!, {r1, r3-r8, lr}
 	tst	r2, #16
-	stmneia	r0!, {r4-r7}
-	ldmfd	sp!, {r4-r7, lr}
+	stmneia	ip!, {r4-r7}
+	ldmfd	sp!, {r4-r8, lr}
 
 #endif
 
 4:	tst	r2, #8
-	stmneia	r0!, {r1, r3}
+	stmneia	ip!, {r1, r3}
 	tst	r2, #4
-	strne	r1, [r0], #4
+	strne	r1, [ip], #4
 /*
  * When we get here, we've got less than 4 bytes to zero.  We
  * may have an unaligned pointer as well.
  */
 5:	tst	r2, #2
-	strneb	r1, [r0], #1
-	strneb	r1, [r0], #1
+	strneb	r1, [ip], #1
+	strneb	r1, [ip], #1
 	tst	r2, #1
-	strneb	r1, [r0], #1
+	strneb	r1, [ip], #1
 	mov	pc, lr
+
+6:	subs	r2, r2, #4		@ 1 do we have enough
+	blt	5b			@ 1 bytes to align with?
+	cmp	r3, #2			@ 1
+	strltb	r1, [ip], #1		@ 1
+	strleb	r1, [ip], #1		@ 1
+	strb	r1, [ip], #1		@ 1
+	add	r2, r2, r3		@ 1 (r2 = r2 - (4 - r3))
+	b	1b
 ENDPROC(memset)
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index fb5c1aa..493a36b 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -5,7 +5,7 @@
 
 # Common objects
 obj-y 			:= time.o clock.o serial.o psc.o \
-			   dma.o usb.o common.o sram.o aemif.o
+			   usb.o common.o sram.o aemif.o
 
 obj-$(CONFIG_DAVINCI_MUX)		+= mux.o
 
diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
index be30997..86f55ba 100644
--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
+++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
@@ -26,12 +26,12 @@
 #include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/spi/spi.h>
+#include <linux/platform_data/edma.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
 #include <mach/irqs.h>
-#include <mach/edma.h>
 #include <mach/mux.h>
 #include <mach/cp_intc.h>
 #include <mach/tnetv107x.h>
diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h
index 12d544b..d26a6bc 100644
--- a/arch/arm/mach-davinci/davinci.h
+++ b/arch/arm/mach-davinci/davinci.h
@@ -23,9 +23,9 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/platform_data/davinci_asp.h>
+#include <linux/platform_data/edma.h>
 #include <linux/platform_data/keyscan-davinci.h>
 #include <mach/hardware.h>
-#include <mach/edma.h>
 
 #include <media/davinci/vpfe_capture.h>
 #include <media/davinci/vpif_types.h>
diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
index 773ab07..ba37760 100644
--- a/arch/arm/mach-davinci/devices-tnetv107x.c
+++ b/arch/arm/mach-davinci/devices-tnetv107x.c
@@ -18,10 +18,10 @@
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/platform_data/edma.h>
 
 #include <mach/common.h>
 #include <mach/irqs.h>
-#include <mach/edma.h>
 #include <mach/tnetv107x.h>
 
 #include "clock.h"
diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c
index 4c48a36..3bdf9f7 100644
--- a/arch/arm/mach-davinci/devices.c
+++ b/arch/arm/mach-davinci/devices.c
@@ -19,9 +19,10 @@
 #include <mach/irqs.h>
 #include <mach/cputype.h>
 #include <mach/mux.h>
-#include <mach/edma.h>
 #include <linux/platform_data/mmc-davinci.h>
 #include <mach/time.h>
+#include <linux/platform_data/edma.h>
+
 
 #include "davinci.h"
 #include "clock.h"
@@ -141,10 +142,10 @@ static struct resource mmcsd0_resources[] = {
 	},
 	/* DMA channels: RX, then TX */
 	{
-		.start = EDMA_CTLR_CHAN(0, DAVINCI_DMA_MMCRXEVT),
+		.start = EDMA_CTLR_CHAN(0, 26),	/* MMCRXEVT */
 		.flags = IORESOURCE_DMA,
 	}, {
-		.start = EDMA_CTLR_CHAN(0, DAVINCI_DMA_MMCTXEVT),
+		.start = EDMA_CTLR_CHAN(0, 27),	/* MMCTXEVT */
 		.flags = IORESOURCE_DMA,
 	},
 };
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index b49c3b7..53998d8 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -19,7 +19,6 @@
 #include <asm/mach/map.h>
 
 #include <mach/cputype.h>
-#include <mach/edma.h>
 #include <mach/psc.h>
 #include <mach/mux.h>
 #include <mach/irqs.h>
@@ -28,6 +27,7 @@
 #include <mach/common.h>
 #include <linux/platform_data/spi-davinci.h>
 #include <mach/gpio-davinci.h>
+#include <linux/platform_data/edma.h>
 
 #include "davinci.h"
 #include "clock.h"
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 6c39805..9b41d33 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -18,11 +18,11 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/spi/spi.h>
+#include <linux/platform_data/edma.h>
 
 #include <asm/mach/map.h>
 
 #include <mach/cputype.h>
-#include <mach/edma.h>
 #include <mach/psc.h>
 #include <mach/mux.h>
 #include <mach/irqs.h>
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 11c79a3..a08910e 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -12,11 +12,11 @@
 #include <linux/clk.h>
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
+#include <linux/platform_data/edma.h>
 
 #include <asm/mach/map.h>
 
 #include <mach/cputype.h>
-#include <mach/edma.h>
 #include <mach/irqs.h>
 #include <mach/psc.h>
 #include <mach/mux.h>
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index ac7b431..6d52a32 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -13,11 +13,11 @@
 #include <linux/clk.h>
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
+#include <linux/platform_data/edma.h>
 
 #include <asm/mach/map.h>
 
 #include <mach/cputype.h>
-#include <mach/edma.h>
 #include <mach/irqs.h>
 #include <mach/psc.h>
 #include <mach/mux.h>
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
deleted file mode 100644
index 45b7c71..0000000
--- a/arch/arm/mach-davinci/dma.c
+++ /dev/null
@@ -1,1591 +0,0 @@
-/*
- * EDMA3 support for DaVinci
- *
- * Copyright (C) 2006-2009 Texas 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <mach/edma.h>
-
-/* Offsets matching "struct edmacc_param" */
-#define PARM_OPT		0x00
-#define PARM_SRC		0x04
-#define PARM_A_B_CNT		0x08
-#define PARM_DST		0x0c
-#define PARM_SRC_DST_BIDX	0x10
-#define PARM_LINK_BCNTRLD	0x14
-#define PARM_SRC_DST_CIDX	0x18
-#define PARM_CCNT		0x1c
-
-#define PARM_SIZE		0x20
-
-/* Offsets for EDMA CC global channel registers and their shadows */
-#define SH_ER		0x00	/* 64 bits */
-#define SH_ECR		0x08	/* 64 bits */
-#define SH_ESR		0x10	/* 64 bits */
-#define SH_CER		0x18	/* 64 bits */
-#define SH_EER		0x20	/* 64 bits */
-#define SH_EECR		0x28	/* 64 bits */
-#define SH_EESR		0x30	/* 64 bits */
-#define SH_SER		0x38	/* 64 bits */
-#define SH_SECR		0x40	/* 64 bits */
-#define SH_IER		0x50	/* 64 bits */
-#define SH_IECR		0x58	/* 64 bits */
-#define SH_IESR		0x60	/* 64 bits */
-#define SH_IPR		0x68	/* 64 bits */
-#define SH_ICR		0x70	/* 64 bits */
-#define SH_IEVAL	0x78
-#define SH_QER		0x80
-#define SH_QEER		0x84
-#define SH_QEECR	0x88
-#define SH_QEESR	0x8c
-#define SH_QSER		0x90
-#define SH_QSECR	0x94
-#define SH_SIZE		0x200
-
-/* Offsets for EDMA CC global registers */
-#define EDMA_REV	0x0000
-#define EDMA_CCCFG	0x0004
-#define EDMA_QCHMAP	0x0200	/* 8 registers */
-#define EDMA_DMAQNUM	0x0240	/* 8 registers (4 on OMAP-L1xx) */
-#define EDMA_QDMAQNUM	0x0260
-#define EDMA_QUETCMAP	0x0280
-#define EDMA_QUEPRI	0x0284
-#define EDMA_EMR	0x0300	/* 64 bits */
-#define EDMA_EMCR	0x0308	/* 64 bits */
-#define EDMA_QEMR	0x0310
-#define EDMA_QEMCR	0x0314
-#define EDMA_CCERR	0x0318
-#define EDMA_CCERRCLR	0x031c
-#define EDMA_EEVAL	0x0320
-#define EDMA_DRAE	0x0340	/* 4 x 64 bits*/
-#define EDMA_QRAE	0x0380	/* 4 registers */
-#define EDMA_QUEEVTENTRY	0x0400	/* 2 x 16 registers */
-#define EDMA_QSTAT	0x0600	/* 2 registers */
-#define EDMA_QWMTHRA	0x0620
-#define EDMA_QWMTHRB	0x0624
-#define EDMA_CCSTAT	0x0640
-
-#define EDMA_M		0x1000	/* global channel registers */
-#define EDMA_ECR	0x1008
-#define EDMA_ECRH	0x100C
-#define EDMA_SHADOW0	0x2000	/* 4 regions shadowing global channels */
-#define EDMA_PARM	0x4000	/* 128 param entries */
-
-#define PARM_OFFSET(param_no)	(EDMA_PARM + ((param_no) << 5))
-
-#define EDMA_DCHMAP	0x0100  /* 64 registers */
-#define CHMAP_EXIST	BIT(24)
-
-#define EDMA_MAX_DMACH           64
-#define EDMA_MAX_PARAMENTRY     512
-
-/*****************************************************************************/
-
-static void __iomem *edmacc_regs_base[EDMA_MAX_CC];
-
-static inline unsigned int edma_read(unsigned ctlr, int offset)
-{
-	return (unsigned int)__raw_readl(edmacc_regs_base[ctlr] + offset);
-}
-
-static inline void edma_write(unsigned ctlr, int offset, int val)
-{
-	__raw_writel(val, edmacc_regs_base[ctlr] + offset);
-}
-static inline void edma_modify(unsigned ctlr, int offset, unsigned and,
-		unsigned or)
-{
-	unsigned val = edma_read(ctlr, offset);
-	val &= and;
-	val |= or;
-	edma_write(ctlr, offset, val);
-}
-static inline void edma_and(unsigned ctlr, int offset, unsigned and)
-{
-	unsigned val = edma_read(ctlr, offset);
-	val &= and;
-	edma_write(ctlr, offset, val);
-}
-static inline void edma_or(unsigned ctlr, int offset, unsigned or)
-{
-	unsigned val = edma_read(ctlr, offset);
-	val |= or;
-	edma_write(ctlr, offset, val);
-}
-static inline unsigned int edma_read_array(unsigned ctlr, int offset, int i)
-{
-	return edma_read(ctlr, offset + (i << 2));
-}
-static inline void edma_write_array(unsigned ctlr, int offset, int i,
-		unsigned val)
-{
-	edma_write(ctlr, offset + (i << 2), val);
-}
-static inline void edma_modify_array(unsigned ctlr, int offset, int i,
-		unsigned and, unsigned or)
-{
-	edma_modify(ctlr, offset + (i << 2), and, or);
-}
-static inline void edma_or_array(unsigned ctlr, int offset, int i, unsigned or)
-{
-	edma_or(ctlr, offset + (i << 2), or);
-}
-static inline void edma_or_array2(unsigned ctlr, int offset, int i, int j,
-		unsigned or)
-{
-	edma_or(ctlr, offset + ((i*2 + j) << 2), or);
-}
-static inline void edma_write_array2(unsigned ctlr, int offset, int i, int j,
-		unsigned val)
-{
-	edma_write(ctlr, offset + ((i*2 + j) << 2), val);
-}
-static inline unsigned int edma_shadow0_read(unsigned ctlr, int offset)
-{
-	return edma_read(ctlr, EDMA_SHADOW0 + offset);
-}
-static inline unsigned int edma_shadow0_read_array(unsigned ctlr, int offset,
-		int i)
-{
-	return edma_read(ctlr, EDMA_SHADOW0 + offset + (i << 2));
-}
-static inline void edma_shadow0_write(unsigned ctlr, int offset, unsigned val)
-{
-	edma_write(ctlr, EDMA_SHADOW0 + offset, val);
-}
-static inline void edma_shadow0_write_array(unsigned ctlr, int offset, int i,
-		unsigned val)
-{
-	edma_write(ctlr, EDMA_SHADOW0 + offset + (i << 2), val);
-}
-static inline unsigned int edma_parm_read(unsigned ctlr, int offset,
-		int param_no)
-{
-	return edma_read(ctlr, EDMA_PARM + offset + (param_no << 5));
-}
-static inline void edma_parm_write(unsigned ctlr, int offset, int param_no,
-		unsigned val)
-{
-	edma_write(ctlr, EDMA_PARM + offset + (param_no << 5), val);
-}
-static inline void edma_parm_modify(unsigned ctlr, int offset, int param_no,
-		unsigned and, unsigned or)
-{
-	edma_modify(ctlr, EDMA_PARM + offset + (param_no << 5), and, or);
-}
-static inline void edma_parm_and(unsigned ctlr, int offset, int param_no,
-		unsigned and)
-{
-	edma_and(ctlr, EDMA_PARM + offset + (param_no << 5), and);
-}
-static inline void edma_parm_or(unsigned ctlr, int offset, int param_no,
-		unsigned or)
-{
-	edma_or(ctlr, EDMA_PARM + offset + (param_no << 5), or);
-}
-
-static inline void set_bits(int offset, int len, unsigned long *p)
-{
-	for (; len > 0; len--)
-		set_bit(offset + (len - 1), p);
-}
-
-static inline void clear_bits(int offset, int len, unsigned long *p)
-{
-	for (; len > 0; len--)
-		clear_bit(offset + (len - 1), p);
-}
-
-/*****************************************************************************/
-
-/* actual number of DMA channels and slots on this silicon */
-struct edma {
-	/* how many dma resources of each type */
-	unsigned	num_channels;
-	unsigned	num_region;
-	unsigned	num_slots;
-	unsigned	num_tc;
-	unsigned	num_cc;
-	enum dma_event_q 	default_queue;
-
-	/* list of channels with no even trigger; terminated by "-1" */
-	const s8	*noevent;
-
-	/* The edma_inuse bit for each PaRAM slot is clear unless the
-	 * channel is in use ... by ARM or DSP, for QDMA, or whatever.
-	 */
-	DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
-
-	/* The edma_unused bit for each channel is clear unless
-	 * it is not being used on this platform. It uses a bit
-	 * of SOC-specific initialization code.
-	 */
-	DECLARE_BITMAP(edma_unused, EDMA_MAX_DMACH);
-
-	unsigned	irq_res_start;
-	unsigned	irq_res_end;
-
-	struct dma_interrupt_data {
-		void (*callback)(unsigned channel, unsigned short ch_status,
-				void *data);
-		void *data;
-	} intr_data[EDMA_MAX_DMACH];
-};
-
-static struct edma *edma_cc[EDMA_MAX_CC];
-static int arch_num_cc;
-
-/* dummy param set used to (re)initialize parameter RAM slots */
-static const struct edmacc_param dummy_paramset = {
-	.link_bcntrld = 0xffff,
-	.ccnt = 1,
-};
-
-/*****************************************************************************/
-
-static void map_dmach_queue(unsigned ctlr, unsigned ch_no,
-		enum dma_event_q queue_no)
-{
-	int bit = (ch_no & 0x7) * 4;
-
-	/* default to low priority queue */
-	if (queue_no == EVENTQ_DEFAULT)
-		queue_no = edma_cc[ctlr]->default_queue;
-
-	queue_no &= 7;
-	edma_modify_array(ctlr, EDMA_DMAQNUM, (ch_no >> 3),
-			~(0x7 << bit), queue_no << bit);
-}
-
-static void __init map_queue_tc(unsigned ctlr, int queue_no, int tc_no)
-{
-	int bit = queue_no * 4;
-	edma_modify(ctlr, EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit));
-}
-
-static void __init assign_priority_to_queue(unsigned ctlr, int queue_no,
-		int priority)
-{
-	int bit = queue_no * 4;
-	edma_modify(ctlr, EDMA_QUEPRI, ~(0x7 << bit),
-			((priority & 0x7) << bit));
-}
-
-/**
- * map_dmach_param - Maps channel number to param entry number
- *
- * This maps the dma channel number to param entry numberter. In
- * other words using the DMA channel mapping registers a param entry
- * can be mapped to any channel
- *
- * Callers are responsible for ensuring the channel mapping logic is
- * included in that particular EDMA variant (Eg : dm646x)
- *
- */
-static void __init map_dmach_param(unsigned ctlr)
-{
-	int i;
-	for (i = 0; i < EDMA_MAX_DMACH; i++)
-		edma_write_array(ctlr, EDMA_DCHMAP , i , (i << 5));
-}
-
-static inline void
-setup_dma_interrupt(unsigned lch,
-	void (*callback)(unsigned channel, u16 ch_status, void *data),
-	void *data)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(lch);
-	lch = EDMA_CHAN_SLOT(lch);
-
-	if (!callback)
-		edma_shadow0_write_array(ctlr, SH_IECR, lch >> 5,
-				BIT(lch & 0x1f));
-
-	edma_cc[ctlr]->intr_data[lch].callback = callback;
-	edma_cc[ctlr]->intr_data[lch].data = data;
-
-	if (callback) {
-		edma_shadow0_write_array(ctlr, SH_ICR, lch >> 5,
-				BIT(lch & 0x1f));
-		edma_shadow0_write_array(ctlr, SH_IESR, lch >> 5,
-				BIT(lch & 0x1f));
-	}
-}
-
-static int irq2ctlr(int irq)
-{
-	if (irq >= edma_cc[0]->irq_res_start && irq <= edma_cc[0]->irq_res_end)
-		return 0;
-	else if (irq >= edma_cc[1]->irq_res_start &&
-		irq <= edma_cc[1]->irq_res_end)
-		return 1;
-
-	return -1;
-}
-
-/******************************************************************************
- *
- * DMA interrupt handler
- *
- *****************************************************************************/
-static irqreturn_t dma_irq_handler(int irq, void *data)
-{
-	int ctlr;
-	u32 sh_ier;
-	u32 sh_ipr;
-	u32 bank;
-
-	ctlr = irq2ctlr(irq);
-	if (ctlr < 0)
-		return IRQ_NONE;
-
-	dev_dbg(data, "dma_irq_handler\n");
-
-	sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 0);
-	if (!sh_ipr) {
-		sh_ipr = edma_shadow0_read_array(ctlr, SH_IPR, 1);
-		if (!sh_ipr)
-			return IRQ_NONE;
-		sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 1);
-		bank = 1;
-	} else {
-		sh_ier = edma_shadow0_read_array(ctlr, SH_IER, 0);
-		bank = 0;
-	}
-
-	do {
-		u32 slot;
-		u32 channel;
-
-		dev_dbg(data, "IPR%d %08x\n", bank, sh_ipr);
-
-		slot = __ffs(sh_ipr);
-		sh_ipr &= ~(BIT(slot));
-
-		if (sh_ier & BIT(slot)) {
-			channel = (bank << 5) | slot;
-			/* Clear the corresponding IPR bits */
-			edma_shadow0_write_array(ctlr, SH_ICR, bank,
-					BIT(slot));
-			if (edma_cc[ctlr]->intr_data[channel].callback)
-				edma_cc[ctlr]->intr_data[channel].callback(
-					channel, DMA_COMPLETE,
-					edma_cc[ctlr]->intr_data[channel].data);
-		}
-	} while (sh_ipr);
-
-	edma_shadow0_write(ctlr, SH_IEVAL, 1);
-	return IRQ_HANDLED;
-}
-
-/******************************************************************************
- *
- * DMA error interrupt handler
- *
- *****************************************************************************/
-static irqreturn_t dma_ccerr_handler(int irq, void *data)
-{
-	int i;
-	int ctlr;
-	unsigned int cnt = 0;
-
-	ctlr = irq2ctlr(irq);
-	if (ctlr < 0)
-		return IRQ_NONE;
-
-	dev_dbg(data, "dma_ccerr_handler\n");
-
-	if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
-	    (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
-	    (edma_read(ctlr, EDMA_QEMR) == 0) &&
-	    (edma_read(ctlr, EDMA_CCERR) == 0))
-		return IRQ_NONE;
-
-	while (1) {
-		int j = -1;
-		if (edma_read_array(ctlr, EDMA_EMR, 0))
-			j = 0;
-		else if (edma_read_array(ctlr, EDMA_EMR, 1))
-			j = 1;
-		if (j >= 0) {
-			dev_dbg(data, "EMR%d %08x\n", j,
-					edma_read_array(ctlr, EDMA_EMR, j));
-			for (i = 0; i < 32; i++) {
-				int k = (j << 5) + i;
-				if (edma_read_array(ctlr, EDMA_EMR, j) &
-							BIT(i)) {
-					/* Clear the corresponding EMR bits */
-					edma_write_array(ctlr, EDMA_EMCR, j,
-							BIT(i));
-					/* Clear any SER */
-					edma_shadow0_write_array(ctlr, SH_SECR,
-								j, BIT(i));
-					if (edma_cc[ctlr]->intr_data[k].
-								callback) {
-						edma_cc[ctlr]->intr_data[k].
-						callback(k,
-						DMA_CC_ERROR,
-						edma_cc[ctlr]->intr_data
-						[k].data);
-					}
-				}
-			}
-		} else if (edma_read(ctlr, EDMA_QEMR)) {
-			dev_dbg(data, "QEMR %02x\n",
-				edma_read(ctlr, EDMA_QEMR));
-			for (i = 0; i < 8; i++) {
-				if (edma_read(ctlr, EDMA_QEMR) & BIT(i)) {
-					/* Clear the corresponding IPR bits */
-					edma_write(ctlr, EDMA_QEMCR, BIT(i));
-					edma_shadow0_write(ctlr, SH_QSECR,
-								BIT(i));
-
-					/* NOTE:  not reported!! */
-				}
-			}
-		} else if (edma_read(ctlr, EDMA_CCERR)) {
-			dev_dbg(data, "CCERR %08x\n",
-				edma_read(ctlr, EDMA_CCERR));
-			/* FIXME:  CCERR.BIT(16) ignored!  much better
-			 * to just write CCERRCLR with CCERR value...
-			 */
-			for (i = 0; i < 8; i++) {
-				if (edma_read(ctlr, EDMA_CCERR) & BIT(i)) {
-					/* Clear the corresponding IPR bits */
-					edma_write(ctlr, EDMA_CCERRCLR, BIT(i));
-
-					/* NOTE:  not reported!! */
-				}
-			}
-		}
-		if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) &&
-		    (edma_read_array(ctlr, EDMA_EMR, 1) == 0) &&
-		    (edma_read(ctlr, EDMA_QEMR) == 0) &&
-		    (edma_read(ctlr, EDMA_CCERR) == 0))
-			break;
-		cnt++;
-		if (cnt > 10)
-			break;
-	}
-	edma_write(ctlr, EDMA_EEVAL, 1);
-	return IRQ_HANDLED;
-}
-
-/******************************************************************************
- *
- * Transfer controller error interrupt handlers
- *
- *****************************************************************************/
-
-#define tc_errs_handled	false	/* disabled as long as they're NOPs */
-
-static irqreturn_t dma_tc0err_handler(int irq, void *data)
-{
-	dev_dbg(data, "dma_tc0err_handler\n");
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t dma_tc1err_handler(int irq, void *data)
-{
-	dev_dbg(data, "dma_tc1err_handler\n");
-	return IRQ_HANDLED;
-}
-
-static int reserve_contiguous_slots(int ctlr, unsigned int id,
-				     unsigned int num_slots,
-				     unsigned int start_slot)
-{
-	int i, j;
-	unsigned int count = num_slots;
-	int stop_slot = start_slot;
-	DECLARE_BITMAP(tmp_inuse, EDMA_MAX_PARAMENTRY);
-
-	for (i = start_slot; i < edma_cc[ctlr]->num_slots; ++i) {
-		j = EDMA_CHAN_SLOT(i);
-		if (!test_and_set_bit(j, edma_cc[ctlr]->edma_inuse)) {
-			/* Record our current beginning slot */
-			if (count == num_slots)
-				stop_slot = i;
-
-			count--;
-			set_bit(j, tmp_inuse);
-
-			if (count == 0)
-				break;
-		} else {
-			clear_bit(j, tmp_inuse);
-
-			if (id == EDMA_CONT_PARAMS_FIXED_EXACT) {
-				stop_slot = i;
-				break;
-			} else {
-				count = num_slots;
-			}
-		}
-	}
-
-	/*
-	 * We have to clear any bits that we set
-	 * if we run out parameter RAM slots, i.e we do find a set
-	 * of contiguous parameter RAM slots but do not find the exact number
-	 * requested as we may reach the total number of parameter RAM slots
-	 */
-	if (i == edma_cc[ctlr]->num_slots)
-		stop_slot = i;
-
-	j = start_slot;
-	for_each_set_bit_from(j, tmp_inuse, stop_slot)
-		clear_bit(j, edma_cc[ctlr]->edma_inuse);
-
-	if (count)
-		return -EBUSY;
-
-	for (j = i - num_slots + 1; j <= i; ++j)
-		memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(j),
-			&dummy_paramset, PARM_SIZE);
-
-	return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1);
-}
-
-static int prepare_unused_channel_list(struct device *dev, void *data)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	int i, ctlr;
-
-	for (i = 0; i < pdev->num_resources; i++) {
-		if ((pdev->resource[i].flags & IORESOURCE_DMA) &&
-				(int)pdev->resource[i].start >= 0) {
-			ctlr = EDMA_CTLR(pdev->resource[i].start);
-			clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start),
-					edma_cc[ctlr]->edma_unused);
-		}
-	}
-
-	return 0;
-}
-
-/*-----------------------------------------------------------------------*/
-
-static bool unused_chan_list_done;
-
-/* Resource alloc/free:  dma channels, parameter RAM slots */
-
-/**
- * edma_alloc_channel - allocate DMA channel and paired parameter RAM
- * @channel: specific channel to allocate; negative for "any unmapped channel"
- * @callback: optional; to be issued on DMA completion or errors
- * @data: passed to callback
- * @eventq_no: an EVENTQ_* constant, used to choose which Transfer
- *	Controller (TC) executes requests using this channel.  Use
- *	EVENTQ_DEFAULT unless you really need a high priority queue.
- *
- * This allocates a DMA channel and its associated parameter RAM slot.
- * The parameter RAM is initialized to hold a dummy transfer.
- *
- * Normal use is to pass a specific channel number as @channel, to make
- * use of hardware events mapped to that channel.  When the channel will
- * be used only for software triggering or event chaining, channels not
- * mapped to hardware events (or mapped to unused events) are preferable.
- *
- * DMA transfers start from a channel using edma_start(), or by
- * chaining.  When the transfer described in that channel's parameter RAM
- * slot completes, that slot's data may be reloaded through a link.
- *
- * DMA errors are only reported to the @callback associated with the
- * channel driving that transfer, but transfer completion callbacks can
- * be sent to another channel under control of the TCC field in
- * the option word of the transfer's parameter RAM set.  Drivers must not
- * use DMA transfer completion callbacks for channels they did not allocate.
- * (The same applies to TCC codes used in transfer chaining.)
- *
- * Returns the number of the channel, else negative errno.
- */
-int edma_alloc_channel(int channel,
-		void (*callback)(unsigned channel, u16 ch_status, void *data),
-		void *data,
-		enum dma_event_q eventq_no)
-{
-	unsigned i, done = 0, ctlr = 0;
-	int ret = 0;
-
-	if (!unused_chan_list_done) {
-		/*
-		 * Scan all the platform devices to find out the EDMA channels
-		 * used and clear them in the unused list, making the rest
-		 * available for ARM usage.
-		 */
-		ret = bus_for_each_dev(&platform_bus_type, NULL, NULL,
-				prepare_unused_channel_list);
-		if (ret < 0)
-			return ret;
-
-		unused_chan_list_done = true;
-	}
-
-	if (channel >= 0) {
-		ctlr = EDMA_CTLR(channel);
-		channel = EDMA_CHAN_SLOT(channel);
-	}
-
-	if (channel < 0) {
-		for (i = 0; i < arch_num_cc; i++) {
-			channel = 0;
-			for (;;) {
-				channel = find_next_bit(edma_cc[i]->edma_unused,
-						edma_cc[i]->num_channels,
-						channel);
-				if (channel == edma_cc[i]->num_channels)
-					break;
-				if (!test_and_set_bit(channel,
-						edma_cc[i]->edma_inuse)) {
-					done = 1;
-					ctlr = i;
-					break;
-				}
-				channel++;
-			}
-			if (done)
-				break;
-		}
-		if (!done)
-			return -ENOMEM;
-	} else if (channel >= edma_cc[ctlr]->num_channels) {
-		return -EINVAL;
-	} else if (test_and_set_bit(channel, edma_cc[ctlr]->edma_inuse)) {
-		return -EBUSY;
-	}
-
-	/* ensure access through shadow region 0 */
-	edma_or_array2(ctlr, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f));
-
-	/* ensure no events are pending */
-	edma_stop(EDMA_CTLR_CHAN(ctlr, channel));
-	memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel),
-			&dummy_paramset, PARM_SIZE);
-
-	if (callback)
-		setup_dma_interrupt(EDMA_CTLR_CHAN(ctlr, channel),
-					callback, data);
-
-	map_dmach_queue(ctlr, channel, eventq_no);
-
-	return EDMA_CTLR_CHAN(ctlr, channel);
-}
-EXPORT_SYMBOL(edma_alloc_channel);
-
-
-/**
- * edma_free_channel - deallocate DMA channel
- * @channel: dma channel returned from edma_alloc_channel()
- *
- * This deallocates the DMA channel and associated parameter RAM slot
- * allocated by edma_alloc_channel().
- *
- * Callers are responsible for ensuring the channel is inactive, and
- * will not be reactivated by linking, chaining, or software calls to
- * edma_start().
- */
-void edma_free_channel(unsigned channel)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(channel);
-	channel = EDMA_CHAN_SLOT(channel);
-
-	if (channel >= edma_cc[ctlr]->num_channels)
-		return;
-
-	setup_dma_interrupt(channel, NULL, NULL);
-	/* REVISIT should probably take out of shadow region 0 */
-
-	memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel),
-			&dummy_paramset, PARM_SIZE);
-	clear_bit(channel, edma_cc[ctlr]->edma_inuse);
-}
-EXPORT_SYMBOL(edma_free_channel);
-
-/**
- * edma_alloc_slot - allocate DMA parameter RAM
- * @slot: specific slot to allocate; negative for "any unused slot"
- *
- * This allocates a parameter RAM slot, initializing it to hold a
- * dummy transfer.  Slots allocated using this routine have not been
- * mapped to a hardware DMA channel, and will normally be used by
- * linking to them from a slot associated with a DMA channel.
- *
- * Normal use is to pass EDMA_SLOT_ANY as the @slot, but specific
- * slots may be allocated on behalf of DSP firmware.
- *
- * Returns the number of the slot, else negative errno.
- */
-int edma_alloc_slot(unsigned ctlr, int slot)
-{
-	if (!edma_cc[ctlr])
-		return -EINVAL;
-
-	if (slot >= 0)
-		slot = EDMA_CHAN_SLOT(slot);
-
-	if (slot < 0) {
-		slot = edma_cc[ctlr]->num_channels;
-		for (;;) {
-			slot = find_next_zero_bit(edma_cc[ctlr]->edma_inuse,
-					edma_cc[ctlr]->num_slots, slot);
-			if (slot == edma_cc[ctlr]->num_slots)
-				return -ENOMEM;
-			if (!test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse))
-				break;
-		}
-	} else if (slot < edma_cc[ctlr]->num_channels ||
-			slot >= edma_cc[ctlr]->num_slots) {
-		return -EINVAL;
-	} else if (test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse)) {
-		return -EBUSY;
-	}
-
-	memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
-			&dummy_paramset, PARM_SIZE);
-
-	return EDMA_CTLR_CHAN(ctlr, slot);
-}
-EXPORT_SYMBOL(edma_alloc_slot);
-
-/**
- * edma_free_slot - deallocate DMA parameter RAM
- * @slot: parameter RAM slot returned from edma_alloc_slot()
- *
- * This deallocates the parameter RAM slot allocated by edma_alloc_slot().
- * Callers are responsible for ensuring the slot is inactive, and will
- * not be activated.
- */
-void edma_free_slot(unsigned slot)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(slot);
-	slot = EDMA_CHAN_SLOT(slot);
-
-	if (slot < edma_cc[ctlr]->num_channels ||
-		slot >= edma_cc[ctlr]->num_slots)
-		return;
-
-	memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
-			&dummy_paramset, PARM_SIZE);
-	clear_bit(slot, edma_cc[ctlr]->edma_inuse);
-}
-EXPORT_SYMBOL(edma_free_slot);
-
-
-/**
- * edma_alloc_cont_slots- alloc contiguous parameter RAM slots
- * The API will return the starting point of a set of
- * contiguous parameter RAM slots that have been requested
- *
- * @id: can only be EDMA_CONT_PARAMS_ANY or EDMA_CONT_PARAMS_FIXED_EXACT
- * or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
- * @count: number of contiguous Paramter RAM slots
- * @slot  - the start value of Parameter RAM slot that should be passed if id
- * is EDMA_CONT_PARAMS_FIXED_EXACT or EDMA_CONT_PARAMS_FIXED_NOT_EXACT
- *
- * If id is EDMA_CONT_PARAMS_ANY then the API starts looking for a set of
- * contiguous Parameter RAM slots from parameter RAM 64 in the case of
- * DaVinci SOCs and 32 in the case of DA8xx SOCs.
- *
- * If id is EDMA_CONT_PARAMS_FIXED_EXACT then the API starts looking for a
- * set of contiguous parameter RAM slots from the "slot" that is passed as an
- * argument to the API.
- *
- * If id is EDMA_CONT_PARAMS_FIXED_NOT_EXACT then the API initially tries
- * starts looking for a set of contiguous parameter RAMs from the "slot"
- * that is passed as an argument to the API. On failure the API will try to
- * find a set of contiguous Parameter RAM slots from the remaining Parameter
- * RAM slots
- */
-int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count)
-{
-	/*
-	 * The start slot requested should be greater than
-	 * the number of channels and lesser than the total number
-	 * of slots
-	 */
-	if ((id != EDMA_CONT_PARAMS_ANY) &&
-		(slot < edma_cc[ctlr]->num_channels ||
-		slot >= edma_cc[ctlr]->num_slots))
-		return -EINVAL;
-
-	/*
-	 * The number of parameter RAM slots requested cannot be less than 1
-	 * and cannot be more than the number of slots minus the number of
-	 * channels
-	 */
-	if (count < 1 || count >
-		(edma_cc[ctlr]->num_slots - edma_cc[ctlr]->num_channels))
-		return -EINVAL;
-
-	switch (id) {
-	case EDMA_CONT_PARAMS_ANY:
-		return reserve_contiguous_slots(ctlr, id, count,
-						 edma_cc[ctlr]->num_channels);
-	case EDMA_CONT_PARAMS_FIXED_EXACT:
-	case EDMA_CONT_PARAMS_FIXED_NOT_EXACT:
-		return reserve_contiguous_slots(ctlr, id, count, slot);
-	default:
-		return -EINVAL;
-	}
-
-}
-EXPORT_SYMBOL(edma_alloc_cont_slots);
-
-/**
- * edma_free_cont_slots - deallocate DMA parameter RAM slots
- * @slot: first parameter RAM of a set of parameter RAM slots to be freed
- * @count: the number of contiguous parameter RAM slots to be freed
- *
- * This deallocates the parameter RAM slots allocated by
- * edma_alloc_cont_slots.
- * Callers/applications need to keep track of sets of contiguous
- * parameter RAM slots that have been allocated using the edma_alloc_cont_slots
- * API.
- * Callers are responsible for ensuring the slots are inactive, and will
- * not be activated.
- */
-int edma_free_cont_slots(unsigned slot, int count)
-{
-	unsigned ctlr, slot_to_free;
-	int i;
-
-	ctlr = EDMA_CTLR(slot);
-	slot = EDMA_CHAN_SLOT(slot);
-
-	if (slot < edma_cc[ctlr]->num_channels ||
-		slot >= edma_cc[ctlr]->num_slots ||
-		count < 1)
-		return -EINVAL;
-
-	for (i = slot; i < slot + count; ++i) {
-		ctlr = EDMA_CTLR(i);
-		slot_to_free = EDMA_CHAN_SLOT(i);
-
-		memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot_to_free),
-			&dummy_paramset, PARM_SIZE);
-		clear_bit(slot_to_free, edma_cc[ctlr]->edma_inuse);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(edma_free_cont_slots);
-
-/*-----------------------------------------------------------------------*/
-
-/* Parameter RAM operations (i) -- read/write partial slots */
-
-/**
- * edma_set_src - set initial DMA source address in parameter RAM slot
- * @slot: parameter RAM slot being configured
- * @src_port: physical address of source (memory, controller FIFO, etc)
- * @addressMode: INCR, except in very rare cases
- * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
- *	width to use when addressing the fifo (e.g. W8BIT, W32BIT)
- *
- * Note that the source address is modified during the DMA transfer
- * according to edma_set_src_index().
- */
-void edma_set_src(unsigned slot, dma_addr_t src_port,
-				enum address_mode mode, enum fifo_width width)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(slot);
-	slot = EDMA_CHAN_SLOT(slot);
-
-	if (slot < edma_cc[ctlr]->num_slots) {
-		unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot);
-
-		if (mode) {
-			/* set SAM and program FWID */
-			i = (i & ~(EDMA_FWID)) | (SAM | ((width & 0x7) << 8));
-		} else {
-			/* clear SAM */
-			i &= ~SAM;
-		}
-		edma_parm_write(ctlr, PARM_OPT, slot, i);
-
-		/* set the source port address
-		   in source register of param structure */
-		edma_parm_write(ctlr, PARM_SRC, slot, src_port);
-	}
-}
-EXPORT_SYMBOL(edma_set_src);
-
-/**
- * edma_set_dest - set initial DMA destination address in parameter RAM slot
- * @slot: parameter RAM slot being configured
- * @dest_port: physical address of destination (memory, controller FIFO, etc)
- * @addressMode: INCR, except in very rare cases
- * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
- *	width to use when addressing the fifo (e.g. W8BIT, W32BIT)
- *
- * Note that the destination address is modified during the DMA transfer
- * according to edma_set_dest_index().
- */
-void edma_set_dest(unsigned slot, dma_addr_t dest_port,
-				 enum address_mode mode, enum fifo_width width)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(slot);
-	slot = EDMA_CHAN_SLOT(slot);
-
-	if (slot < edma_cc[ctlr]->num_slots) {
-		unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot);
-
-		if (mode) {
-			/* set DAM and program FWID */
-			i = (i & ~(EDMA_FWID)) | (DAM | ((width & 0x7) << 8));
-		} else {
-			/* clear DAM */
-			i &= ~DAM;
-		}
-		edma_parm_write(ctlr, PARM_OPT, slot, i);
-		/* set the destination port address
-		   in dest register of param structure */
-		edma_parm_write(ctlr, PARM_DST, slot, dest_port);
-	}
-}
-EXPORT_SYMBOL(edma_set_dest);
-
-/**
- * edma_get_position - returns the current transfer points
- * @slot: parameter RAM slot being examined
- * @src: pointer to source port position
- * @dst: pointer to destination port position
- *
- * Returns current source and destination addresses for a particular
- * parameter RAM slot.  Its channel should not be active when this is called.
- */
-void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst)
-{
-	struct edmacc_param temp;
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(slot);
-	slot = EDMA_CHAN_SLOT(slot);
-
-	edma_read_slot(EDMA_CTLR_CHAN(ctlr, slot), &temp);
-	if (src != NULL)
-		*src = temp.src;
-	if (dst != NULL)
-		*dst = temp.dst;
-}
-EXPORT_SYMBOL(edma_get_position);
-
-/**
- * edma_set_src_index - configure DMA source address indexing
- * @slot: parameter RAM slot being configured
- * @src_bidx: byte offset between source arrays in a frame
- * @src_cidx: byte offset between source frames in a block
- *
- * Offsets are specified to support either contiguous or discontiguous
- * memory transfers, or repeated access to a hardware register, as needed.
- * When accessing hardware registers, both offsets are normally zero.
- */
-void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(slot);
-	slot = EDMA_CHAN_SLOT(slot);
-
-	if (slot < edma_cc[ctlr]->num_slots) {
-		edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot,
-				0xffff0000, src_bidx);
-		edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot,
-				0xffff0000, src_cidx);
-	}
-}
-EXPORT_SYMBOL(edma_set_src_index);
-
-/**
- * edma_set_dest_index - configure DMA destination address indexing
- * @slot: parameter RAM slot being configured
- * @dest_bidx: byte offset between destination arrays in a frame
- * @dest_cidx: byte offset between destination frames in a block
- *
- * Offsets are specified to support either contiguous or discontiguous
- * memory transfers, or repeated access to a hardware register, as needed.
- * When accessing hardware registers, both offsets are normally zero.
- */
-void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(slot);
-	slot = EDMA_CHAN_SLOT(slot);
-
-	if (slot < edma_cc[ctlr]->num_slots) {
-		edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot,
-				0x0000ffff, dest_bidx << 16);
-		edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot,
-				0x0000ffff, dest_cidx << 16);
-	}
-}
-EXPORT_SYMBOL(edma_set_dest_index);
-
-/**
- * edma_set_transfer_params - configure DMA transfer parameters
- * @slot: parameter RAM slot being configured
- * @acnt: how many bytes per array (at least one)
- * @bcnt: how many arrays per frame (at least one)
- * @ccnt: how many frames per block (at least one)
- * @bcnt_rld: used only for A-Synchronized transfers; this specifies
- *	the value to reload into bcnt when it decrements to zero
- * @sync_mode: ASYNC or ABSYNC
- *
- * See the EDMA3 documentation to understand how to configure and link
- * transfers using the fields in PaRAM slots.  If you are not doing it
- * all at once with edma_write_slot(), you will use this routine
- * plus two calls each for source and destination, setting the initial
- * address and saying how to index that address.
- *
- * An example of an A-Synchronized transfer is a serial link using a
- * single word shift register.  In that case, @acnt would be equal to
- * that word size; the serial controller issues a DMA synchronization
- * event to transfer each word, and memory access by the DMA transfer
- * controller will be word-at-a-time.
- *
- * An example of an AB-Synchronized transfer is a device using a FIFO.
- * In that case, @acnt equals the FIFO width and @bcnt equals its depth.
- * The controller with the FIFO issues DMA synchronization events when
- * the FIFO threshold is reached, and the DMA transfer controller will
- * transfer one frame to (or from) the FIFO.  It will probably use
- * efficient burst modes to access memory.
- */
-void edma_set_transfer_params(unsigned slot,
-		u16 acnt, u16 bcnt, u16 ccnt,
-		u16 bcnt_rld, enum sync_dimension sync_mode)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(slot);
-	slot = EDMA_CHAN_SLOT(slot);
-
-	if (slot < edma_cc[ctlr]->num_slots) {
-		edma_parm_modify(ctlr, PARM_LINK_BCNTRLD, slot,
-				0x0000ffff, bcnt_rld << 16);
-		if (sync_mode == ASYNC)
-			edma_parm_and(ctlr, PARM_OPT, slot, ~SYNCDIM);
-		else
-			edma_parm_or(ctlr, PARM_OPT, slot, SYNCDIM);
-		/* Set the acount, bcount, ccount registers */
-		edma_parm_write(ctlr, PARM_A_B_CNT, slot, (bcnt << 16) | acnt);
-		edma_parm_write(ctlr, PARM_CCNT, slot, ccnt);
-	}
-}
-EXPORT_SYMBOL(edma_set_transfer_params);
-
-/**
- * edma_link - link one parameter RAM slot to another
- * @from: parameter RAM slot originating the link
- * @to: parameter RAM slot which is the link target
- *
- * The originating slot should not be part of any active DMA transfer.
- */
-void edma_link(unsigned from, unsigned to)
-{
-	unsigned ctlr_from, ctlr_to;
-
-	ctlr_from = EDMA_CTLR(from);
-	from = EDMA_CHAN_SLOT(from);
-	ctlr_to = EDMA_CTLR(to);
-	to = EDMA_CHAN_SLOT(to);
-
-	if (from >= edma_cc[ctlr_from]->num_slots)
-		return;
-	if (to >= edma_cc[ctlr_to]->num_slots)
-		return;
-	edma_parm_modify(ctlr_from, PARM_LINK_BCNTRLD, from, 0xffff0000,
-				PARM_OFFSET(to));
-}
-EXPORT_SYMBOL(edma_link);
-
-/**
- * edma_unlink - cut link from one parameter RAM slot
- * @from: parameter RAM slot originating the link
- *
- * The originating slot should not be part of any active DMA transfer.
- * Its link is set to 0xffff.
- */
-void edma_unlink(unsigned from)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(from);
-	from = EDMA_CHAN_SLOT(from);
-
-	if (from >= edma_cc[ctlr]->num_slots)
-		return;
-	edma_parm_or(ctlr, PARM_LINK_BCNTRLD, from, 0xffff);
-}
-EXPORT_SYMBOL(edma_unlink);
-
-/*-----------------------------------------------------------------------*/
-
-/* Parameter RAM operations (ii) -- read/write whole parameter sets */
-
-/**
- * edma_write_slot - write parameter RAM data for slot
- * @slot: number of parameter RAM slot being modified
- * @param: data to be written into parameter RAM slot
- *
- * Use this to assign all parameters of a transfer at once.  This
- * allows more efficient setup of transfers than issuing multiple
- * calls to set up those parameters in small pieces, and provides
- * complete control over all transfer options.
- */
-void edma_write_slot(unsigned slot, const struct edmacc_param *param)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(slot);
-	slot = EDMA_CHAN_SLOT(slot);
-
-	if (slot >= edma_cc[ctlr]->num_slots)
-		return;
-	memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot), param,
-			PARM_SIZE);
-}
-EXPORT_SYMBOL(edma_write_slot);
-
-/**
- * edma_read_slot - read parameter RAM data from slot
- * @slot: number of parameter RAM slot being copied
- * @param: where to store copy of parameter RAM data
- *
- * Use this to read data from a parameter RAM slot, perhaps to
- * save them as a template for later reuse.
- */
-void edma_read_slot(unsigned slot, struct edmacc_param *param)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(slot);
-	slot = EDMA_CHAN_SLOT(slot);
-
-	if (slot >= edma_cc[ctlr]->num_slots)
-		return;
-	memcpy_fromio(param, edmacc_regs_base[ctlr] + PARM_OFFSET(slot),
-			PARM_SIZE);
-}
-EXPORT_SYMBOL(edma_read_slot);
-
-/*-----------------------------------------------------------------------*/
-
-/* Various EDMA channel control operations */
-
-/**
- * edma_pause - pause dma on a channel
- * @channel: on which edma_start() has been called
- *
- * This temporarily disables EDMA hardware events on the specified channel,
- * preventing them from triggering new transfers on its behalf
- */
-void edma_pause(unsigned channel)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(channel);
-	channel = EDMA_CHAN_SLOT(channel);
-
-	if (channel < edma_cc[ctlr]->num_channels) {
-		unsigned int mask = BIT(channel & 0x1f);
-
-		edma_shadow0_write_array(ctlr, SH_EECR, channel >> 5, mask);
-	}
-}
-EXPORT_SYMBOL(edma_pause);
-
-/**
- * edma_resume - resumes dma on a paused channel
- * @channel: on which edma_pause() has been called
- *
- * This re-enables EDMA hardware events on the specified channel.
- */
-void edma_resume(unsigned channel)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(channel);
-	channel = EDMA_CHAN_SLOT(channel);
-
-	if (channel < edma_cc[ctlr]->num_channels) {
-		unsigned int mask = BIT(channel & 0x1f);
-
-		edma_shadow0_write_array(ctlr, SH_EESR, channel >> 5, mask);
-	}
-}
-EXPORT_SYMBOL(edma_resume);
-
-/**
- * edma_start - start dma on a channel
- * @channel: channel being activated
- *
- * Channels with event associations will be triggered by their hardware
- * events, and channels without such associations will be triggered by
- * software.  (At this writing there is no interface for using software
- * triggers except with channels that don't support hardware triggers.)
- *
- * Returns zero on success, else negative errno.
- */
-int edma_start(unsigned channel)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(channel);
-	channel = EDMA_CHAN_SLOT(channel);
-
-	if (channel < edma_cc[ctlr]->num_channels) {
-		int j = channel >> 5;
-		unsigned int mask = BIT(channel & 0x1f);
-
-		/* EDMA channels without event association */
-		if (test_bit(channel, edma_cc[ctlr]->edma_unused)) {
-			pr_debug("EDMA: ESR%d %08x\n", j,
-				edma_shadow0_read_array(ctlr, SH_ESR, j));
-			edma_shadow0_write_array(ctlr, SH_ESR, j, mask);
-			return 0;
-		}
-
-		/* EDMA channel with event association */
-		pr_debug("EDMA: ER%d %08x\n", j,
-			edma_shadow0_read_array(ctlr, SH_ER, j));
-		/* Clear any pending event or error */
-		edma_write_array(ctlr, EDMA_ECR, j, mask);
-		edma_write_array(ctlr, EDMA_EMCR, j, mask);
-		/* Clear any SER */
-		edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
-		edma_shadow0_write_array(ctlr, SH_EESR, j, mask);
-		pr_debug("EDMA: EER%d %08x\n", j,
-			edma_shadow0_read_array(ctlr, SH_EER, j));
-		return 0;
-	}
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL(edma_start);
-
-/**
- * edma_stop - stops dma on the channel passed
- * @channel: channel being deactivated
- *
- * When @lch is a channel, any active transfer is paused and
- * all pending hardware events are cleared.  The current transfer
- * may not be resumed, and the channel's Parameter RAM should be
- * reinitialized before being reused.
- */
-void edma_stop(unsigned channel)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(channel);
-	channel = EDMA_CHAN_SLOT(channel);
-
-	if (channel < edma_cc[ctlr]->num_channels) {
-		int j = channel >> 5;
-		unsigned int mask = BIT(channel & 0x1f);
-
-		edma_shadow0_write_array(ctlr, SH_EECR, j, mask);
-		edma_shadow0_write_array(ctlr, SH_ECR, j, mask);
-		edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
-		edma_write_array(ctlr, EDMA_EMCR, j, mask);
-
-		pr_debug("EDMA: EER%d %08x\n", j,
-				edma_shadow0_read_array(ctlr, SH_EER, j));
-
-		/* REVISIT:  consider guarding against inappropriate event
-		 * chaining by overwriting with dummy_paramset.
-		 */
-	}
-}
-EXPORT_SYMBOL(edma_stop);
-
-/******************************************************************************
- *
- * It cleans ParamEntry qand bring back EDMA to initial state if media has
- * been removed before EDMA has finished.It is usedful for removable media.
- * Arguments:
- *      ch_no     - channel no
- *
- * Return: zero on success, or corresponding error no on failure
- *
- * FIXME this should not be needed ... edma_stop() should suffice.
- *
- *****************************************************************************/
-
-void edma_clean_channel(unsigned channel)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(channel);
-	channel = EDMA_CHAN_SLOT(channel);
-
-	if (channel < edma_cc[ctlr]->num_channels) {
-		int j = (channel >> 5);
-		unsigned int mask = BIT(channel & 0x1f);
-
-		pr_debug("EDMA: EMR%d %08x\n", j,
-				edma_read_array(ctlr, EDMA_EMR, j));
-		edma_shadow0_write_array(ctlr, SH_ECR, j, mask);
-		/* Clear the corresponding EMR bits */
-		edma_write_array(ctlr, EDMA_EMCR, j, mask);
-		/* Clear any SER */
-		edma_shadow0_write_array(ctlr, SH_SECR, j, mask);
-		edma_write(ctlr, EDMA_CCERRCLR, BIT(16) | BIT(1) | BIT(0));
-	}
-}
-EXPORT_SYMBOL(edma_clean_channel);
-
-/*
- * edma_clear_event - clear an outstanding event on the DMA channel
- * Arguments:
- *	channel - channel number
- */
-void edma_clear_event(unsigned channel)
-{
-	unsigned ctlr;
-
-	ctlr = EDMA_CTLR(channel);
-	channel = EDMA_CHAN_SLOT(channel);
-
-	if (channel >= edma_cc[ctlr]->num_channels)
-		return;
-	if (channel < 32)
-		edma_write(ctlr, EDMA_ECR, BIT(channel));
-	else
-		edma_write(ctlr, EDMA_ECRH, BIT(channel - 32));
-}
-EXPORT_SYMBOL(edma_clear_event);
-
-/*-----------------------------------------------------------------------*/
-
-static int __init edma_probe(struct platform_device *pdev)
-{
-	struct edma_soc_info	**info = pdev->dev.platform_data;
-	const s8		(*queue_priority_mapping)[2];
-	const s8		(*queue_tc_mapping)[2];
-	int			i, j, off, ln, found = 0;
-	int			status = -1;
-	const s16		(*rsv_chans)[2];
-	const s16		(*rsv_slots)[2];
-	int			irq[EDMA_MAX_CC] = {0, 0};
-	int			err_irq[EDMA_MAX_CC] = {0, 0};
-	struct resource		*r[EDMA_MAX_CC] = {NULL};
-	resource_size_t		len[EDMA_MAX_CC];
-	char			res_name[10];
-	char			irq_name[10];
-
-	if (!info)
-		return -ENODEV;
-
-	for (j = 0; j < EDMA_MAX_CC; j++) {
-		sprintf(res_name, "edma_cc%d", j);
-		r[j] = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						res_name);
-		if (!r[j] || !info[j]) {
-			if (found)
-				break;
-			else
-				return -ENODEV;
-		} else {
-			found = 1;
-		}
-
-		len[j] = resource_size(r[j]);
-
-		r[j] = request_mem_region(r[j]->start, len[j],
-			dev_name(&pdev->dev));
-		if (!r[j]) {
-			status = -EBUSY;
-			goto fail1;
-		}
-
-		edmacc_regs_base[j] = ioremap(r[j]->start, len[j]);
-		if (!edmacc_regs_base[j]) {
-			status = -EBUSY;
-			goto fail1;
-		}
-
-		edma_cc[j] = kzalloc(sizeof(struct edma), GFP_KERNEL);
-		if (!edma_cc[j]) {
-			status = -ENOMEM;
-			goto fail1;
-		}
-
-		edma_cc[j]->num_channels = min_t(unsigned, info[j]->n_channel,
-							EDMA_MAX_DMACH);
-		edma_cc[j]->num_slots = min_t(unsigned, info[j]->n_slot,
-							EDMA_MAX_PARAMENTRY);
-		edma_cc[j]->num_cc = min_t(unsigned, info[j]->n_cc,
-							EDMA_MAX_CC);
-
-		edma_cc[j]->default_queue = info[j]->default_queue;
-
-		dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n",
-			edmacc_regs_base[j]);
-
-		for (i = 0; i < edma_cc[j]->num_slots; i++)
-			memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i),
-					&dummy_paramset, PARM_SIZE);
-
-		/* Mark all channels as unused */
-		memset(edma_cc[j]->edma_unused, 0xff,
-			sizeof(edma_cc[j]->edma_unused));
-
-		if (info[j]->rsv) {
-
-			/* Clear the reserved channels in unused list */
-			rsv_chans = info[j]->rsv->rsv_chans;
-			if (rsv_chans) {
-				for (i = 0; rsv_chans[i][0] != -1; i++) {
-					off = rsv_chans[i][0];
-					ln = rsv_chans[i][1];
-					clear_bits(off, ln,
-						edma_cc[j]->edma_unused);
-				}
-			}
-
-			/* Set the reserved slots in inuse list */
-			rsv_slots = info[j]->rsv->rsv_slots;
-			if (rsv_slots) {
-				for (i = 0; rsv_slots[i][0] != -1; i++) {
-					off = rsv_slots[i][0];
-					ln = rsv_slots[i][1];
-					set_bits(off, ln,
-						edma_cc[j]->edma_inuse);
-				}
-			}
-		}
-
-		sprintf(irq_name, "edma%d", j);
-		irq[j] = platform_get_irq_byname(pdev, irq_name);
-		edma_cc[j]->irq_res_start = irq[j];
-		status = request_irq(irq[j], dma_irq_handler, 0, "edma",
-					&pdev->dev);
-		if (status < 0) {
-			dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
-				irq[j], status);
-			goto fail;
-		}
-
-		sprintf(irq_name, "edma%d_err", j);
-		err_irq[j] = platform_get_irq_byname(pdev, irq_name);
-		edma_cc[j]->irq_res_end = err_irq[j];
-		status = request_irq(err_irq[j], dma_ccerr_handler, 0,
-					"edma_error", &pdev->dev);
-		if (status < 0) {
-			dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
-				err_irq[j], status);
-			goto fail;
-		}
-
-		for (i = 0; i < edma_cc[j]->num_channels; i++)
-			map_dmach_queue(j, i, info[j]->default_queue);
-
-		queue_tc_mapping = info[j]->queue_tc_mapping;
-		queue_priority_mapping = info[j]->queue_priority_mapping;
-
-		/* Event queue to TC mapping */
-		for (i = 0; queue_tc_mapping[i][0] != -1; i++)
-			map_queue_tc(j, queue_tc_mapping[i][0],
-					queue_tc_mapping[i][1]);
-
-		/* Event queue priority mapping */
-		for (i = 0; queue_priority_mapping[i][0] != -1; i++)
-			assign_priority_to_queue(j,
-						queue_priority_mapping[i][0],
-						queue_priority_mapping[i][1]);
-
-		/* Map the channel to param entry if channel mapping logic
-		 * exist
-		 */
-		if (edma_read(j, EDMA_CCCFG) & CHMAP_EXIST)
-			map_dmach_param(j);
-
-		for (i = 0; i < info[j]->n_region; i++) {
-			edma_write_array2(j, EDMA_DRAE, i, 0, 0x0);
-			edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
-			edma_write_array(j, EDMA_QRAE, i, 0x0);
-		}
-		arch_num_cc++;
-	}
-
-	if (tc_errs_handled) {
-		status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0,
-					"edma_tc0", &pdev->dev);
-		if (status < 0) {
-			dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
-				IRQ_TCERRINT0, status);
-			return status;
-		}
-		status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0,
-					"edma_tc1", &pdev->dev);
-		if (status < 0) {
-			dev_dbg(&pdev->dev, "request_irq %d --> %d\n",
-				IRQ_TCERRINT, status);
-			return status;
-		}
-	}
-
-	return 0;
-
-fail:
-	for (i = 0; i < EDMA_MAX_CC; i++) {
-		if (err_irq[i])
-			free_irq(err_irq[i], &pdev->dev);
-		if (irq[i])
-			free_irq(irq[i], &pdev->dev);
-	}
-fail1:
-	for (i = 0; i < EDMA_MAX_CC; i++) {
-		if (r[i])
-			release_mem_region(r[i]->start, len[i]);
-		if (edmacc_regs_base[i])
-			iounmap(edmacc_regs_base[i]);
-		kfree(edma_cc[i]);
-	}
-	return status;
-}
-
-
-static struct platform_driver edma_driver = {
-	.driver.name	= "edma",
-};
-
-static int __init edma_init(void)
-{
-	return platform_driver_probe(&edma_driver, edma_probe);
-}
-arch_initcall(edma_init);
-
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index 700d311..9d77f9b 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -20,8 +20,8 @@
 #include <linux/videodev2.h>
 
 #include <mach/serial.h>
-#include <mach/edma.h>
 #include <mach/pm.h>
+#include <linux/platform_data/edma.h>
 #include <linux/platform_data/i2c-davinci.h>
 #include <linux/platform_data/mmc-davinci.h>
 #include <linux/platform_data/usb-davinci.h>
diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h
deleted file mode 100644
index 7e84c90..0000000
--- a/arch/arm/mach-davinci/include/mach/edma.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- *  TI DAVINCI dma definitions
- *
- *  Copyright (C) 2006-2009 Texas 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  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.
- *
- */
-
-/*
- * This EDMA3 programming framework exposes two basic kinds of resource:
- *
- *  Channel	Triggers transfers, usually from a hardware event but
- *		also manually or by "chaining" from DMA completions.
- *		Each channel is coupled to a Parameter RAM (PaRAM) slot.
- *
- *  Slot	Each PaRAM slot holds a DMA transfer descriptor (PaRAM
- *		"set"), source and destination addresses, a link to a
- *		next PaRAM slot (if any), options for the transfer, and
- *		instructions for updating those addresses.  There are
- *		more than twice as many slots as event channels.
- *
- * Each PaRAM set describes a sequence of transfers, either for one large
- * buffer or for several discontiguous smaller buffers.  An EDMA transfer
- * is driven only from a channel, which performs the transfers specified
- * in its PaRAM slot until there are no more transfers.  When that last
- * transfer completes, the "link" field may be used to reload the channel's
- * PaRAM slot with a new transfer descriptor.
- *
- * The EDMA Channel Controller (CC) maps requests from channels into physical
- * Transfer Controller (TC) requests when the channel triggers (by hardware
- * or software events, or by chaining).  The two physical DMA channels provided
- * by the TCs are thus shared by many logical channels.
- *
- * DaVinci hardware also has a "QDMA" mechanism which is not currently
- * supported through this interface.  (DSP firmware uses it though.)
- */
-
-#ifndef EDMA_H_
-#define EDMA_H_
-
-/* PaRAM slots are laid out like this */
-struct edmacc_param {
-	unsigned int opt;
-	unsigned int src;
-	unsigned int a_b_cnt;
-	unsigned int dst;
-	unsigned int src_dst_bidx;
-	unsigned int link_bcntrld;
-	unsigned int src_dst_cidx;
-	unsigned int ccnt;
-};
-
-#define CCINT0_INTERRUPT     16
-#define CCERRINT_INTERRUPT   17
-#define TCERRINT0_INTERRUPT   18
-#define TCERRINT1_INTERRUPT   19
-
-/* fields in edmacc_param.opt */
-#define SAM		BIT(0)
-#define DAM		BIT(1)
-#define SYNCDIM		BIT(2)
-#define STATIC		BIT(3)
-#define EDMA_FWID	(0x07 << 8)
-#define TCCMODE		BIT(11)
-#define EDMA_TCC(t)	((t) << 12)
-#define TCINTEN		BIT(20)
-#define ITCINTEN	BIT(21)
-#define TCCHEN		BIT(22)
-#define ITCCHEN		BIT(23)
-
-#define TRWORD (0x7<<2)
-#define PAENTRY (0x1ff<<5)
-
-/* Drivers should avoid using these symbolic names for dm644x
- * channels, and use platform_device IORESOURCE_DMA resources
- * instead.  (Other DaVinci chips have different peripherals
- * and thus have different DMA channel mappings.)
- */
-#define DAVINCI_DMA_MCBSP_TX              2
-#define DAVINCI_DMA_MCBSP_RX              3
-#define DAVINCI_DMA_VPSS_HIST             4
-#define DAVINCI_DMA_VPSS_H3A              5
-#define DAVINCI_DMA_VPSS_PRVU             6
-#define DAVINCI_DMA_VPSS_RSZ              7
-#define DAVINCI_DMA_IMCOP_IMXINT          8
-#define DAVINCI_DMA_IMCOP_VLCDINT         9
-#define DAVINCI_DMA_IMCO_PASQINT         10
-#define DAVINCI_DMA_IMCOP_DSQINT         11
-#define DAVINCI_DMA_SPI_SPIX             16
-#define DAVINCI_DMA_SPI_SPIR             17
-#define DAVINCI_DMA_UART0_URXEVT0        18
-#define DAVINCI_DMA_UART0_UTXEVT0        19
-#define DAVINCI_DMA_UART1_URXEVT1        20
-#define DAVINCI_DMA_UART1_UTXEVT1        21
-#define DAVINCI_DMA_UART2_URXEVT2        22
-#define DAVINCI_DMA_UART2_UTXEVT2        23
-#define DAVINCI_DMA_MEMSTK_MSEVT         24
-#define DAVINCI_DMA_MMCRXEVT             26
-#define DAVINCI_DMA_MMCTXEVT             27
-#define DAVINCI_DMA_I2C_ICREVT           28
-#define DAVINCI_DMA_I2C_ICXEVT           29
-#define DAVINCI_DMA_GPIO_GPINT0          32
-#define DAVINCI_DMA_GPIO_GPINT1          33
-#define DAVINCI_DMA_GPIO_GPINT2          34
-#define DAVINCI_DMA_GPIO_GPINT3          35
-#define DAVINCI_DMA_GPIO_GPINT4          36
-#define DAVINCI_DMA_GPIO_GPINT5          37
-#define DAVINCI_DMA_GPIO_GPINT6          38
-#define DAVINCI_DMA_GPIO_GPINT7          39
-#define DAVINCI_DMA_GPIO_GPBNKINT0       40
-#define DAVINCI_DMA_GPIO_GPBNKINT1       41
-#define DAVINCI_DMA_GPIO_GPBNKINT2       42
-#define DAVINCI_DMA_GPIO_GPBNKINT3       43
-#define DAVINCI_DMA_GPIO_GPBNKINT4       44
-#define DAVINCI_DMA_TIMER0_TINT0         48
-#define DAVINCI_DMA_TIMER1_TINT1         49
-#define DAVINCI_DMA_TIMER2_TINT2         50
-#define DAVINCI_DMA_TIMER3_TINT3         51
-#define DAVINCI_DMA_PWM0                 52
-#define DAVINCI_DMA_PWM1                 53
-#define DAVINCI_DMA_PWM2                 54
-
-/* DA830 specific EDMA3 information */
-#define EDMA_DA830_NUM_DMACH		32
-#define EDMA_DA830_NUM_TCC		32
-#define EDMA_DA830_NUM_PARAMENTRY	128
-#define EDMA_DA830_NUM_EVQUE		2
-#define EDMA_DA830_NUM_TC		2
-#define EDMA_DA830_CHMAP_EXIST		0
-#define EDMA_DA830_NUM_REGIONS		4
-#define DA830_DMACH2EVENT_MAP0		0x000FC03Fu
-#define DA830_DMACH2EVENT_MAP1		0x00000000u
-#define DA830_EDMA_ARM_OWN		0x30FFCCFFu
-
-/*ch_status paramater of callback function possible values*/
-#define DMA_COMPLETE 1
-#define DMA_CC_ERROR 2
-#define DMA_TC1_ERROR 3
-#define DMA_TC2_ERROR 4
-
-enum address_mode {
-	INCR = 0,
-	FIFO = 1
-};
-
-enum fifo_width {
-	W8BIT = 0,
-	W16BIT = 1,
-	W32BIT = 2,
-	W64BIT = 3,
-	W128BIT = 4,
-	W256BIT = 5
-};
-
-enum dma_event_q {
-	EVENTQ_0 = 0,
-	EVENTQ_1 = 1,
-	EVENTQ_2 = 2,
-	EVENTQ_3 = 3,
-	EVENTQ_DEFAULT = -1
-};
-
-enum sync_dimension {
-	ASYNC = 0,
-	ABSYNC = 1
-};
-
-#define EDMA_CTLR_CHAN(ctlr, chan)	(((ctlr) << 16) | (chan))
-#define EDMA_CTLR(i)			((i) >> 16)
-#define EDMA_CHAN_SLOT(i)		((i) & 0xffff)
-
-#define EDMA_CHANNEL_ANY		-1	/* for edma_alloc_channel() */
-#define EDMA_SLOT_ANY			-1	/* for edma_alloc_slot() */
-#define EDMA_CONT_PARAMS_ANY		 1001
-#define EDMA_CONT_PARAMS_FIXED_EXACT	 1002
-#define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003
-
-#define EDMA_MAX_CC               2
-
-/* alloc/free DMA channels and their dedicated parameter RAM slots */
-int edma_alloc_channel(int channel,
-	void (*callback)(unsigned channel, u16 ch_status, void *data),
-	void *data, enum dma_event_q);
-void edma_free_channel(unsigned channel);
-
-/* alloc/free parameter RAM slots */
-int edma_alloc_slot(unsigned ctlr, int slot);
-void edma_free_slot(unsigned slot);
-
-/* alloc/free a set of contiguous parameter RAM slots */
-int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count);
-int edma_free_cont_slots(unsigned slot, int count);
-
-/* calls that operate on part of a parameter RAM slot */
-void edma_set_src(unsigned slot, dma_addr_t src_port,
-				enum address_mode mode, enum fifo_width);
-void edma_set_dest(unsigned slot, dma_addr_t dest_port,
-				 enum address_mode mode, enum fifo_width);
-void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst);
-void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx);
-void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx);
-void edma_set_transfer_params(unsigned slot, u16 acnt, u16 bcnt, u16 ccnt,
-		u16 bcnt_rld, enum sync_dimension sync_mode);
-void edma_link(unsigned from, unsigned to);
-void edma_unlink(unsigned from);
-
-/* calls that operate on an entire parameter RAM slot */
-void edma_write_slot(unsigned slot, const struct edmacc_param *params);
-void edma_read_slot(unsigned slot, struct edmacc_param *params);
-
-/* channel control operations */
-int edma_start(unsigned channel);
-void edma_stop(unsigned channel);
-void edma_clean_channel(unsigned channel);
-void edma_clear_event(unsigned channel);
-void edma_pause(unsigned channel);
-void edma_resume(unsigned channel);
-
-struct edma_rsv_info {
-
-	const s16	(*rsv_chans)[2];
-	const s16	(*rsv_slots)[2];
-};
-
-/* platform_data for EDMA driver */
-struct edma_soc_info {
-
-	/* how many dma resources of each type */
-	unsigned	n_channel;
-	unsigned	n_region;
-	unsigned	n_slot;
-	unsigned	n_tc;
-	unsigned	n_cc;
-	/*
-	 * Default queue is expected to be a low-priority queue.
-	 * This way, long transfers on the default queue started
-	 * by the codec engine will not cause audio defects.
-	 */
-	enum dma_event_q	default_queue;
-
-	/* Resource reservation for other cores */
-	struct edma_rsv_info	*rsv;
-
-	const s8	(*queue_tc_mapping)[2];
-	const s8	(*queue_priority_mapping)[2];
-};
-
-#endif
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 41b581f..d8486c8 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -18,6 +18,8 @@ config ARCH_OMAP2PLUS_TYPICAL
 	select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4
 	select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4
 	select VFP
+	select OF_OVERLAY
+	select OF_RESOLVE
 	help
 	  Compile a kernel suitable for booting most boards
 
@@ -35,6 +37,9 @@ config ARCH_OMAP2
 	default y
 	select CPU_V6
 	select MULTI_IRQ_HANDLER
+	select MACH_AM335XEVM
+	select MACH_AM335XIAEVM
+	select MACH_TAM335X
 	select SOC_HAS_OMAP2_SDRC
 	select COMMON_CLK
 
@@ -117,6 +122,9 @@ config SOC_AM33XX
 	select CPU_V7
 	select MULTI_IRQ_HANDLER
 	select COMMON_CLK
+	select MACH_AM335XEVM
+	select MACH_AM335XIAEVM
+	select MACH_TAM335X
 
 config OMAP_PACKAGE_ZAF
        bool
@@ -153,6 +161,15 @@ config MACH_OMAP_GENERIC
 	  Support for generic TI OMAP2+ boards using Flattened Device Tree.
 	  More information at Documentation/devicetree
 
+config MACH_AM335XEVM
+       bool
+
+config MACH_AM335XIAEVM
+       bool
+
+config MACH_TAM335X
+       bool
+
 config MACH_OMAP2_TUSB6010
 	bool
 	depends on ARCH_OMAP2 && SOC_OMAP2420
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 947cafe..afecbbc 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -53,6 +53,7 @@ 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_SOC_AM33XX)		+= am33xx-restart.o
 obj-$(CONFIG_ARCH_OMAP3)		+= omap3-restart.o
 
 # Pin multiplexing
@@ -295,4 +296,7 @@ endif
 emac-$(CONFIG_TI_DAVINCI_EMAC)		:= am35xx-emac.o
 obj-y					+= $(emac-m) $(emac-y)
 
+cpsw-$(CONFIG_TI_CPSW)			:= am33xx-cpsw.o
+obj-y					+= $(cpsw-m) $(cpsw-y)
+
 obj-y					+= common-board-devices.o twl-common.o dss-common.o
diff --git a/arch/arm/mach-omap2/am33xx-cpsw.c b/arch/arm/mach-omap2/am33xx-cpsw.c
new file mode 100644
index 0000000..5a674d9
--- /dev/null
+++ b/arch/arm/mach-omap2/am33xx-cpsw.c
@@ -0,0 +1,94 @@
+/*
+ * am335x specific cpsw dt fixups
+ *
+ * This program is free software; 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/init.h>
+#include <linux/etherdevice.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
+
+#include "soc.h"
+#include "control.h"
+
+/**
+ * am33xx_dt_cpsw_set_mac_from_efuse - Add mac-address property using
+ * ethernet hwaddr from efuse
+ * @np:		Pointer to the cpsw slave to set mac address of
+ * @idx:	Mac address index to use from efuse
+ */
+static void am33xx_dt_cpsw_set_mac_from_efuse(struct device_node *np, int idx)
+{
+	struct property *prop;
+	u32 lo, hi;
+	u8 *mac;
+
+	switch (idx) {
+	case 0:
+		lo = omap_ctrl_readl(AM33XX_CONTROL_MAC_ID0_LOW);
+		hi = omap_ctrl_readl(AM33XX_CONTROL_MAC_ID0_HIGH);
+		break;
+
+	case 1:
+		lo = omap_ctrl_readl(AM33XX_CONTROL_MAC_ID1_LOW);
+		hi = omap_ctrl_readl(AM33XX_CONTROL_MAC_ID1_HIGH);
+		break;
+
+	default:
+		pr_err("cpsw.%d: too many slaves found\n", idx);
+		return;
+	}
+
+	prop = kzalloc(sizeof(*prop) + ETH_ALEN, GFP_KERNEL);
+	if (!prop)
+		return;
+
+	prop->value = prop + 1;
+	prop->length = ETH_ALEN;
+	prop->name = kstrdup("mac-address", GFP_KERNEL);
+	if (!prop->name) {
+		kfree(prop);
+		return;
+	}
+
+	mac = prop->value;
+
+	mac[0] = hi;
+	mac[1] = hi >> 8;
+	mac[2] = hi >> 16;
+	mac[3] = hi >> 24;
+	mac[4] = lo;
+	mac[5] = lo >> 8;
+
+	of_update_property(np, prop);
+
+	pr_info("cpsw.%d: No hwaddr in dt. Using %pM from efuse\n", idx, mac);
+}
+
+static int __init am33xx_dt_cpsw_mac_fixup(void)
+{
+	struct device_node *np, *slave;
+	int idx = 0;
+
+	if (!soc_is_am33xx())
+		return -ENODEV;
+
+	for_each_compatible_node(np, NULL, "ti,cpsw")
+		for_each_node_by_name(slave, "slave") {
+			if (!of_get_mac_address(slave))
+				am33xx_dt_cpsw_set_mac_from_efuse(slave, idx);
+			idx++;
+		}
+
+	return 0;
+}
+arch_initcall(am33xx_dt_cpsw_mac_fixup);
diff --git a/arch/arm/mach-omap2/am33xx-restart.c b/arch/arm/mach-omap2/am33xx-restart.c
new file mode 100644
index 0000000..88e4fa8
--- /dev/null
+++ b/arch/arm/mach-omap2/am33xx-restart.c
@@ -0,0 +1,34 @@
+/*
+ * am33xx-restart.c - Code common to all AM33xx machines.
+ *
+ * This program is free software; you can redistribute it 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 "common.h"
+#include "prm-regbits-33xx.h"
+#include "prm33xx.h"
+
+/**
+ * am3xx_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 am33xx_restart(char mode, const char *cmd)
+{
+	/* TODO: Handle mode and cmd if necessary */
+
+	am33xx_prm_rmw_reg_bits(AM33XX_GLOBAL_WARM_SW_RST_MASK,
+				AM33XX_GLOBAL_WARM_SW_RST_MASK,
+				AM33XX_PRM_DEVICE_MOD,
+				AM33XX_PRM_RSTCTRL_OFFSET);
+
+	/* OCP barrier */
+	(void)am33xx_prm_read_reg(AM33XX_PRM_DEVICE_MOD,
+				  AM33XX_PRM_RSTCTRL_OFFSET);
+}
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 4815ea6..1337f2c 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -27,6 +27,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -263,6 +264,7 @@ static void __init omap_2430sdp_init(void)
 	omap_hsmmc_init(mmc);
 
 	omap_mux_init_signal("usb0hs_stp", OMAP_PULL_ENA | OMAP_PULL_UP);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 
 	board_smc91x_init();
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index bb73afc..8a2e242 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -25,6 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -579,6 +580,7 @@ static void __init omap_3430sdp_init(void)
 	omap_ads7846_init(1, gpio_pendown, 310, NULL);
 	omap_serial_init();
 	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	board_smc91x_init();
 	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 1cc6696..8e8efcc 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -28,6 +28,7 @@
 #include <linux/leds_pwm.h>
 #include <linux/platform_data/omap4-keypad.h>
 #include <linux/usb/musb.h>
+#include <linux/usb/phy.h>
 
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
@@ -696,6 +697,7 @@ static void __init omap_4430sdp_init(void)
 	omap4_sdp4430_wifi_init();
 	omap4_twl6030_hsmmc_init(mmc);
 
+	usb_bind_phy("musb-hdrc.0.auto", 0, "omap-usb2.1.auto");
 	usb_musb_init(&musb_board_data);
 
 	status = omap_ethernet_init();
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index b3102c2..f1172f2 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -30,6 +30,7 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/tdo24m.h>
@@ -724,6 +725,7 @@ static void __init cm_t3x_common_init(void)
 	cm_t35_init_display();
 	omap_twl4030_audio_init("cm-t3x");
 
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	cm_t35_init_usbh();
 	cm_t35_init_camera();
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 12865af..77cade52 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -29,6 +29,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
@@ -622,6 +623,7 @@ static void __init devkit8000_init(void)
 
 	omap_ads7846_init(2, OMAP3_DEVKIT_TS_GPIO, 0, NULL);
 
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	board_nand_init(devkit8000_nand_partitions,
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 53cb380b..fac00f0 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -141,6 +141,7 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
 	.init_machine	= omap_generic_init,
 	.timer		= &omap3_am33xx_timer,
 	.dt_compat	= am33xx_boards_compat,
+	.restart	= am33xx_restart,
 MACHINE_END
 #endif
 
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 0f24cb8..15e5881 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -18,6 +18,7 @@
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
+#include <linux/usb/phy.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
@@ -625,6 +626,7 @@ static void __init igep_init(void)
 	omap_serial_init();
 	omap_sdrc_init(m65kxxxxam_sdrc_params,
 				  m65kxxxxam_sdrc_params);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 
 	igep_flash_init();
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 0869f4f..3b5510a 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -28,6 +28,7 @@
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
 #include <asm/mach-types.h>
@@ -418,6 +419,7 @@ static void __init omap_ldp_init(void)
 	omap_ads7846_init(1, 54, 310, NULL);
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
 			ZOOM_NAND_CS, 0, nand_default_timings);
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 22c483d..a5cb58c 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/leds.h>
 #include <linux/gpio.h>
+#include <linux/irq.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include <linux/opp.h>
@@ -30,16 +31,20 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 
 #include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 #include <linux/i2c/twl.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
+#include <linux/spi/spi.h>
 
 #include <video/omapdss.h>
+#include <video/omap-panel-generic-dpi.h>
 #include <video/omap-panel-tfp410.h>
 #include <linux/platform_data/mtd-nand-omap2.h>
 
@@ -86,12 +91,16 @@ static struct {
 	int dvi_pd_gpio;
 	int usr_button_gpio;
 	int mmc_caps;
+	char *lcd_driver_name;
+	int lcd_pwren;
 } beagle_config = {
 	.mmc1_gpio_wp = -EINVAL,
 	.usb_pwr_level = GPIOF_OUT_INIT_LOW,
 	.dvi_pd_gpio = -EINVAL,
 	.usr_button_gpio = 4,
 	.mmc_caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+	.lcd_driver_name = "",
+	.lcd_pwren = 156,
 };
 
 static struct gpio omap3_beagle_rev_gpios[] __initdata = {
@@ -162,6 +171,203 @@ static void __init omap3_beagle_init_rev(void)
 	}
 }
 
+char expansionboard_name[16];
+char expansionboard2_name[16];
+char camera_name[16];
+char wl12xx_name[16];
+
+enum {
+	EXPANSION_MMC_NONE = 0,
+	EXPANSION_MMC_ZIPPY,
+	EXPANSION_MMC_WIFI,
+};
+
+enum {
+	EXPANSION_I2C_NONE = 0,
+	EXPANSION_I2C_ZIPPY,
+	EXPANSION_I2C_7ULCD,
+};
+
+static struct {
+	int mmc_settings;
+	int i2c_settings;
+} expansion_config = {
+	.mmc_settings = EXPANSION_MMC_NONE,
+	.i2c_settings = EXPANSION_I2C_NONE,
+};
+
+#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
+#include <linux/regulator/fixed.h>
+#include <linux/ti_wilink_st.h>
+#include <linux/wl12xx.h>
+
+#define OMAP_BEAGLE_WLAN_EN_GPIO    (139)
+#define OMAP_BEAGLE_BT_EN_GPIO      (138)
+#define OMAP_BEAGLE_WLAN_IRQ_GPIO   (137)
+#define OMAP_BEAGLE_FM_EN_BT_WU     (136)
+
+struct wl12xx_platform_data omap_beagle_wlan_data __initdata = {
+	.board_ref_clock = WL12XX_REFCLOCK_38, /* 38.4 MHz */
+};
+
+struct wl12xx_platform_data omap_beagle_wlan_data_26mhz __initdata = {
+	.board_ref_clock = WL12XX_REFCLOCK_26, /* 26 MHz */
+};
+
+static struct ti_st_plat_data wilink_platform_data = {
+	.nshutdown_gpio	= OMAP_BEAGLE_BT_EN_GPIO,
+	.dev_name		= "/dev/ttyO1",
+	.flow_cntrl		= 1,
+	.baud_rate		= 3000000,
+	.chip_enable	= NULL,
+	.suspend		= NULL,
+	.resume			= NULL,
+};
+
+static struct platform_device wl12xx_device = {
+		.name		= "kim",
+		.id			= -1,
+		.dev.platform_data = &wilink_platform_data,
+};
+
+static struct platform_device btwilink_device = {
+	.name	= "btwilink",
+	.id	= -1,
+};
+#endif
+
+static struct regulator_consumer_supply beagle_vmmc2_supply =
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
+
+static struct regulator_init_data beagle_vmmc2 = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &beagle_vmmc2_supply,
+};
+
+#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
+static struct fixed_voltage_config beagle_vwlan = {
+	.supply_name = "vwl1271",
+	.microvolts = 1800000,  /* 1.8V */
+	.gpio = OMAP_BEAGLE_WLAN_EN_GPIO,
+	.startup_delay = 70000, /* 70ms */
+	.enable_high = 1,
+	.enabled_at_boot = 0,
+	.init_data = &beagle_vmmc2,
+};
+
+static struct platform_device omap_vwlan_device = {
+	.name		= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data = &beagle_vwlan,
+	},
+};
+#endif
+
+//rcn-ee: this is just a fake regulator, the zippy hardware provides 3.3/1.8 with jumper..
+static struct fixed_voltage_config beagle_vzippy = {
+	.supply_name = "vzippy",
+	.microvolts = 3300000,  /* 3.3V */
+	.startup_delay = 70000, /* 70ms */
+	.enable_high = 1,
+	.enabled_at_boot = 0,
+	.init_data = &beagle_vmmc2,
+};
+
+static struct platform_device omap_zippy_device = {
+	.name	= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data = &beagle_vzippy,
+	},
+};
+
+#define OMAP3BEAGLE_GPIO_ZIPPY_MMC_WP 141
+#define OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD 162
+
+#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
+#include <linux/platform_data/spi-omap2-mcspi.h>
+#include <linux/spi/spi.h>
+
+#define OMAP3BEAGLE_GPIO_ENC28J60_IRQ 157
+
+static struct omap2_mcspi_device_config enc28j60_spi_chip_info = {
+	.turbo_mode	= 0,
+};
+
+static struct spi_board_info omap3beagle_zippy_spi_board_info[] __initdata = {
+	{
+		.modalias		= "enc28j60",
+		.bus_num		= 4,
+		.chip_select	= 0,
+		.max_speed_hz	= 20000000,
+		.controller_data	= &enc28j60_spi_chip_info,
+	},
+};
+
+static void __init omap3beagle_enc28j60_init(void)
+{
+	if ((gpio_request(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, "ENC28J60_IRQ") == 0) &&
+	    (gpio_direction_input(OMAP3BEAGLE_GPIO_ENC28J60_IRQ) == 0)) {
+		gpio_export(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, 0);
+		omap3beagle_zippy_spi_board_info[0].irq = gpio_to_irq(OMAP3BEAGLE_GPIO_ENC28J60_IRQ);
+		irq_set_irq_type(omap3beagle_zippy_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
+	} else {
+		pr_err("Beagle expansionboard: could not obtain gpio for ENC28J60_IRQ\n");
+		return;
+	}
+
+	spi_register_board_info(omap3beagle_zippy_spi_board_info,
+			ARRAY_SIZE(omap3beagle_zippy_spi_board_info));
+}
+
+#else
+static inline void __init omap3beagle_enc28j60_init(void) { return; }
+#endif
+
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
+#include <linux/platform_data/spi-omap2-mcspi.h>
+#include <linux/spi/spi.h>
+
+#define OMAP3BEAGLE_GPIO_KS8851_IRQ 157
+
+static struct omap2_mcspi_device_config ks8851_spi_chip_info = {
+	.turbo_mode	= 0,
+};
+
+static struct spi_board_info omap3beagle_zippy2_spi_board_info[] __initdata = {
+	{
+		.modalias		= "ks8851",
+		.bus_num		= 4,
+		.chip_select	= 0,
+		.max_speed_hz	= 36000000,
+		.controller_data	= &ks8851_spi_chip_info,
+	},
+};
+
+static void __init omap3beagle_ks8851_init(void)
+{
+	if ((gpio_request(OMAP3BEAGLE_GPIO_KS8851_IRQ, "KS8851_IRQ") == 0) &&
+	    (gpio_direction_input(OMAP3BEAGLE_GPIO_KS8851_IRQ) == 0)) {
+		gpio_export(OMAP3BEAGLE_GPIO_KS8851_IRQ, 0);
+		omap3beagle_zippy2_spi_board_info[0].irq = gpio_to_irq(OMAP3BEAGLE_GPIO_KS8851_IRQ);
+		irq_set_irq_type(omap3beagle_zippy2_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
+	} else {
+		pr_err("Beagle expansionboard: could not obtain gpio for KS8851_IRQ\n");
+		return;
+	}
+
+	spi_register_board_info(omap3beagle_zippy2_spi_board_info,
+			ARRAY_SIZE(omap3beagle_zippy2_spi_board_info));
+}
+
+#else
+static inline void __init omap3beagle_ks8851_init(void) { return; }
+#endif
+
 static struct mtd_partition omap3beagle_nand_partitions[] = {
 	/* All the partition sizes are listed in terms of NAND block size */
 	{
@@ -215,9 +421,53 @@ static struct omap_dss_device beagle_tv_device = {
 	.phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
 };
 
+static int beagle_enable_lcd(struct omap_dss_device *dssdev)
+{
+	if (gpio_is_valid(beagle_config.lcd_pwren)) {
+		pr_info("%s: Enabling LCD\n", __FUNCTION__);
+		gpio_set_value(beagle_config.lcd_pwren, 0);
+	} else {
+		pr_info("%s: Invalid LCD enable GPIO: %d\n",
+			__FUNCTION__, beagle_config.lcd_pwren);
+	}
+
+	return 0;
+}
+
+static void beagle_disable_lcd(struct omap_dss_device *dssdev)
+{
+	if (gpio_is_valid(beagle_config.lcd_pwren)) {
+		pr_info("%s: Disabling LCD\n", __FUNCTION__);
+		gpio_set_value(beagle_config.lcd_pwren, 1);
+	} else {
+		pr_info("%s: Invalid LCD enable GPIO: %d\n",
+			__FUNCTION__, beagle_config.lcd_pwren);
+	}
+
+	return;
+}
+
+static struct panel_generic_dpi_data lcd_panel = {
+	.name = "tfc_s9700rtwv35tr-01b",
+	.platform_enable = beagle_enable_lcd,
+	.platform_disable = beagle_disable_lcd,
+};
+
+static struct omap_dss_device beagle_lcd_device = {
+	.type                   = OMAP_DISPLAY_TYPE_DPI,
+	.name                   = "lcd",
+	.driver_name		= "generic_dpi_panel",
+	.phy.dpi.data_lines     = 24,
+	.platform_enable        = beagle_enable_lcd,
+	.platform_disable       = beagle_disable_lcd,
+	.reset_gpio 		= -EINVAL,
+	.data			= &lcd_panel,
+};
+
 static struct omap_dss_device *beagle_dss_devices[] = {
 	&beagle_dvi_device,
 	&beagle_tv_device,
+	&beagle_lcd_device,
 };
 
 static struct omap_dss_board_info beagle_dss_data = {
@@ -238,6 +488,43 @@ static struct omap2_hsmmc_info mmc[] = {
 	{}	/* Terminator */
 };
 
+static struct omap2_hsmmc_info mmc_zippy[] = {
+	{
+		.mmc		= 1,
+		.caps		= MMC_CAP_4_BIT_DATA,
+		.gpio_wp	= -EINVAL,
+		.deferred	= true,
+	},
+	{
+		.mmc		= 2,
+		.caps		= MMC_CAP_4_BIT_DATA,
+		.gpio_wp	= OMAP3BEAGLE_GPIO_ZIPPY_MMC_WP,
+		.gpio_cd	= OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD,
+		.transceiver	= true,
+		.deferred	= true,
+	},
+	{}	/* Terminator */
+};
+
+static struct omap2_hsmmc_info mmcbbt[] = {
+	{
+		.mmc		= 1,
+		.caps		= MMC_CAP_4_BIT_DATA,
+		.gpio_wp	= -EINVAL,
+		.deferred	= true,
+	},
+	{
+		.name		= "wl1271",
+		.mmc		= 2,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
+		.gpio_wp	= -EINVAL,
+		.gpio_cd	= -EINVAL,
+		.ocr_mask	= MMC_VDD_165_195,
+		.nonremovable	= true,
+	},
+	{}	/* Terminator */
+};
+
 static struct regulator_consumer_supply beagle_vmmc1_supply[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -246,6 +533,14 @@ static struct regulator_consumer_supply beagle_vsim_supply[] = {
 	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
 };
 
+static struct regulator_consumer_supply beagle_vaux3_supply = {
+	.supply		= "cam_1v8",
+};
+
+static struct regulator_consumer_supply beagle_vaux4_supply = {
+	.supply		= "cam_2v8",
+};
+
 static struct gpio_led gpio_leds[];
 
 static int beagle_twl_gpio_setup(struct device *dev,
@@ -253,10 +548,28 @@ static int beagle_twl_gpio_setup(struct device *dev,
 {
 	int r;
 
-	mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
-	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
-	mmc[0].gpio_cd = gpio + 0;
-	omap_hsmmc_late_init(mmc);
+	switch (expansion_config.mmc_settings) {
+	case EXPANSION_MMC_WIFI:
+		mmcbbt[0].gpio_wp = beagle_config.mmc1_gpio_wp;
+		/* gpio + 0 is "mmc0_cd" (input/IRQ) */
+		mmcbbt[0].gpio_cd = gpio + 0;
+
+		omap_hsmmc_late_init(mmcbbt);
+		break;
+	case EXPANSION_MMC_ZIPPY:
+		mmc_zippy[0].gpio_wp = beagle_config.mmc1_gpio_wp;
+		/* gpio + 0 is "mmc0_cd" (input/IRQ) */
+		mmc_zippy[0].gpio_cd = gpio + 0;
+
+		omap_hsmmc_late_init(mmc_zippy);
+		break;
+	default:
+		mmc[0].gpio_wp = beagle_config.mmc1_gpio_wp;
+		/* gpio + 0 is "mmc0_cd" (input/IRQ) */
+		mmc[0].gpio_cd = gpio + 0;
+
+		omap_hsmmc_late_init(mmc);
+	}
 
 	/*
 	 * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
@@ -336,11 +649,43 @@ static struct regulator_init_data beagle_vsim = {
 	.consumer_supplies	= beagle_vsim_supply,
 };
 
+/* VAUX3 for CAM_1V8 */
+static struct regulator_init_data beagle_vaux3 = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &beagle_vaux3_supply,
+};
+
+/* VAUX4 for CAM_2V8 */
+static struct regulator_init_data beagle_vaux4 = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &beagle_vaux4_supply,
+};
+
 static struct twl4030_platform_data beagle_twldata = {
 	/* platform_data for children goes here */
 	.gpio		= &beagle_gpio_data,
 	.vmmc1		= &beagle_vmmc1,
 	.vsim		= &beagle_vsim,
+	.vaux3		= &beagle_vaux3,
+	.vaux4		= &beagle_vaux4,
 };
 
 static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
@@ -349,16 +694,149 @@ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
        },
 };
 
+static struct i2c_board_info __initdata zippy_i2c2_rtc[] = {
+#if defined(CONFIG_RTC_DRV_DS1307) || defined(CONFIG_RTC_DRV_DS1307_MODULE)
+	{
+		I2C_BOARD_INFO("ds1307", 0x68),
+	},
+#endif
+};
+
+#if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
+/* Touchscreen */
+#include <linux/i2c/tsc2007.h>
+
+#define OMAP3BEAGLE_TSC2007_GPIO 157
+
+static int omap3beagle_tsc2007_get_pendown_state(void)
+{
+	return !gpio_get_value(OMAP3BEAGLE_TSC2007_GPIO);
+}
+
+static struct tsc2007_platform_data tsc2007_info = {
+	.model = 2007,
+	.x_plate_ohms = 180,
+	.get_pendown_state = omap3beagle_tsc2007_get_pendown_state,
+};
+
+static struct i2c_board_info __initdata beagle_i2c2_bbtoys_ulcd[] = {
+	{
+		I2C_BOARD_INFO("tlc59108", 0x40),
+	},
+	{
+		I2C_BOARD_INFO("tsc2007", 0x48),
+		.platform_data = &tsc2007_info,
+	},
+};
+
+static void __init omap3beagle_tsc2007_init(void)
+{
+	int r;
+
+	omap_mux_init_gpio(OMAP3BEAGLE_TSC2007_GPIO, OMAP_PIN_INPUT_PULLUP);
+
+	r = gpio_request_one(OMAP3BEAGLE_TSC2007_GPIO, GPIOF_IN, "tsc2007_pen_down");
+	if (r < 0) {
+		pr_err("Beagle expansionboard: failed to request GPIO#%d for "
+		"tsc2007 pen down IRQ\n", OMAP3BEAGLE_TSC2007_GPIO);
+		return;
+	}
+
+	beagle_i2c2_bbtoys_ulcd[0].irq = gpio_to_irq(OMAP3BEAGLE_TSC2007_GPIO);
+	irq_set_irq_type(gpio_to_irq(OMAP3BEAGLE_TSC2007_GPIO), IRQ_TYPE_EDGE_FALLING);
+}
+#else
+static struct i2c_board_info __initdata beagle_i2c2_bbtoys_ulcd[] = {};
+#endif
+
+#if defined(CONFIG_VIDEO_MT9P031)
+/* needed for: omap3_beagle_late_initcall */
+#include "devices.h"
+#include <media/omap3isp.h>
+#include <media/mt9p031.h>
+/* needed for: v4l2_dev_to_isp_device */
+#include "../../../drivers/media/platform/omap3isp/isp.h"
+
+#define MT9P031_XCLK		ISP_XCLK_A
+
+#define MT9P031_RESET_GPIO	98
+#define MT9P031_EXT_FREQ	21000000
+#define MT9P031_TARGET_FREQ	48000000
+
+#define MT9P031_I2C_ADDR	0x48
+#define MT9P031_I2C_BUS		2
+
+static struct regulator *reg_1v8, *reg_2v8;
+
+static int beagle_cam_set_xclk(struct v4l2_subdev *subdev, int hz)
+{
+	struct isp_device *isp = v4l2_dev_to_isp_device(subdev->v4l2_dev);
+
+	return isp->platform_cb.set_xclk(isp, hz, MT9P031_XCLK);
+}
+
+static struct mt9p031_platform_data beagle_mt9p031_platform_data = {
+	.set_xclk	= beagle_cam_set_xclk,
+	.reset		= MT9P031_RESET_GPIO,
+	.ext_freq	= MT9P031_EXT_FREQ,
+	.target_freq	= MT9P031_TARGET_FREQ,
+};
+
+static struct i2c_board_info mt9p031_camera_i2c_device = {
+	I2C_BOARD_INFO("mt9p031", MT9P031_I2C_ADDR),
+	.platform_data = &beagle_mt9p031_platform_data,
+};
+
+static struct isp_subdev_i2c_board_info mt9p031_camera_subdevs[] = {
+	{
+		.board_info = &mt9p031_camera_i2c_device,
+		.i2c_adapter_id = MT9P031_I2C_BUS,
+	},
+	{ NULL, 0, },
+};
+
+static struct isp_v4l2_subdevs_group beagle_camera_subdevs[] = {
+	{
+		.subdevs = mt9p031_camera_subdevs,
+		.interface = ISP_INTERFACE_PARALLEL,
+		.bus = {
+			.parallel = {
+				.data_lane_shift = 0,
+				.clk_pol = 1,
+			}
+		},
+	},
+	{ },
+};
+
+static struct isp_platform_data beagle_isp_platform_data = {
+	.subdevs = beagle_camera_subdevs,
+};
+#endif
+
 static int __init omap3_beagle_i2c_init(void)
 {
 	omap3_pmic_get_config(&beagle_twldata,
 			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC |
-			TWL_COMMON_PDATA_AUDIO,
+			TWL_COMMON_PDATA_AUDIO | TWL_COMMON_PDATA_POWER,
 			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
 
 	beagle_twldata.vpll2->constraints.name = "VDVI";
 
 	omap3_pmic_init("twl4030", &beagle_twldata);
+
+	switch (expansion_config.i2c_settings) {
+	case EXPANSION_I2C_7ULCD:
+		omap_register_i2c_bus(2, 400,  beagle_i2c2_bbtoys_ulcd,
+							ARRAY_SIZE(beagle_i2c2_bbtoys_ulcd));
+		break;
+	case EXPANSION_I2C_ZIPPY:
+		omap_register_i2c_bus(2, 400, zippy_i2c2_rtc, ARRAY_SIZE(zippy_i2c2_rtc));
+		break;
+	default:
+		omap_register_i2c_bus(2, 400, NULL, 0);
+	}
+
 	/* Bus 3 is attached to the DVI port where devices like the pico DLP
 	 * projector don't work reliably with 400kHz */
 	omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom));
@@ -448,6 +926,54 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
+static int __init expansionboard_setup(char *str)
+{
+	if (!machine_is_omap3_beagle())
+		return 0;
+
+	if (!str)
+		return -EINVAL;
+	strncpy(expansionboard_name, str, 16);
+	pr_info("Beagle expansionboard: %s\n", expansionboard_name);
+	return 0;
+}
+
+static int __init expansionboard2_setup(char *str)
+{
+	if (!machine_is_omap3_beagle())
+		return 0;
+
+	if (!str)
+		return -EINVAL;
+	strncpy(expansionboard2_name, str, 16);
+	pr_info("Beagle expansionboard2: %s\n", expansionboard2_name);
+	return 0;
+}
+
+static int __init camera_setup(char *str)
+{
+	if (!machine_is_omap3_beagle())
+		return 0;
+
+	if (!str)
+		return -EINVAL;
+	strncpy(camera_name, str, 16);
+	pr_info("Beagle camera: %s\n", camera_name);
+	return 0;
+}
+
+static int __init wl12xx_setup(char *str)
+{
+	if (!machine_is_omap3_beagle())
+		return 0;
+
+	if (!str)
+		return -EINVAL;
+	strncpy(wl12xx_name, str, 16);
+	pr_info("Beagle wl12xx clk: %s\n", wl12xx_name);
+	return 0;
+}
+
 static int __init beagle_opp_init(void)
 {
 	int r = 0;
@@ -496,15 +1022,142 @@ static int __init beagle_opp_init(void)
 }
 device_initcall(beagle_opp_init);
 
+static void __init omap3_beagle_config_mcspi3_mux(void)
+{
+	/* NOTE: Clock pins need to be in input mode */
+	omap_mux_init_signal("sdmmc2_clk.mcspi3_clk", OMAP_PIN_INPUT);
+	omap_mux_init_signal("sdmmc2_cmd.mcspi3_simo", OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("sdmmc2_dat0.mcspi3_somi", OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("sdmmc2_dat2.mcspi3_cs1", OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("sdmmc2_dat3.mcspi3_cs0", OMAP_PIN_OUTPUT);
+}
+
+static void __init omap3_beagle_config_mcspi4_mux(void)
+{
+	/* NOTE: Clock pins need to be in input mode */
+	omap_mux_init_signal("mcbsp1_clkr.mcspi4_clk", OMAP_PIN_INPUT);
+	omap_mux_init_signal("mcbsp1_dx.mcspi4_simo", OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("mcbsp1_dr.mcspi4_somi", OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("mcbsp1_fsx.mcspi4_cs0", OMAP_PIN_OUTPUT);
+}
+
+static void __init omap3_beagle_config_mcbsp3_mux(void)
+{
+	omap_mux_init_signal("mcbsp3_fsx.uart2_rx", OMAP_PIN_INPUT);
+	omap_mux_init_signal("uart2_cts.mcbsp3_dx", OMAP_PIN_OUTPUT);
+	omap_mux_init_signal("uart2_rts.mcbsp3_dr", OMAP_PIN_INPUT);
+	/* NOTE: Clock pins need to be in input mode */
+	omap_mux_init_signal("uart2_tx.mcbsp3_clkx", OMAP_PIN_INPUT);
+}
+
+static void __init omap3_beagle_config_fpga_mux(void)
+{
+	omap3_beagle_config_mcbsp3_mux();
+	omap3_beagle_config_mcspi3_mux();
+	omap3_beagle_config_mcspi4_mux();
+}
+
+static struct spi_board_info beagle_mcspi_board_info[] = {
+	/* spi 3.0 */
+	{
+		.modalias	= "spidev",
+		.max_speed_hz	= 48000000, //48 Mbps
+		.bus_num	= 3,
+		.chip_select	= 0,
+		.mode = SPI_MODE_1,
+	},
+	/* spi 3.1 */
+	{
+		.modalias	= "spidev",
+		.max_speed_hz	= 48000000, //48 Mbps
+		.bus_num	= 3,
+		.chip_select	= 1,
+		.mode = SPI_MODE_1,
+	},
+	/* spi 4.0 */
+	{
+		.modalias	= "spidev",
+		.max_speed_hz	= 48000000, //48 Mbps
+		.bus_num	= 4,
+		.chip_select	= 0,
+		.mode = SPI_MODE_1,
+	},
+};
+
 static void __init omap3_beagle_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
 
+	if ((!strcmp(expansionboard_name, "zippy")) || (!strcmp(expansionboard_name, "zippy2")))
+	{
+		pr_info("Beagle expansionboard: initializing zippy mmc\n");
+		platform_device_register(&omap_zippy_device);
+
+		expansion_config.i2c_settings = EXPANSION_I2C_ZIPPY;
+		expansion_config.mmc_settings = EXPANSION_MMC_ZIPPY;
+
+		omap_mux_init_gpio(OMAP3BEAGLE_GPIO_ZIPPY_MMC_WP, OMAP_PIN_INPUT);
+		omap_mux_init_gpio(OMAP3BEAGLE_GPIO_ZIPPY_MMC_CD, OMAP_PIN_INPUT);
+	}
+
+	if ((!strcmp(expansionboard_name, "bbtoys-wifi")) || (!strcmp(expansionboard_name, "lsr-com6l-adpt")))
+	{
+	#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
+		pr_info("Beagle expansion: wl12xx: setting up gpio pinmux\n");
+
+		omap_mux_init_gpio(OMAP_BEAGLE_FM_EN_BT_WU, OMAP_PIN_OUTPUT);
+		omap_mux_init_gpio(OMAP_BEAGLE_BT_EN_GPIO, OMAP_PIN_OUTPUT);
+		omap_mux_init_gpio(OMAP_BEAGLE_WLAN_EN_GPIO, OMAP_PIN_OUTPUT);
+
+		omap_mux_init_gpio(OMAP_BEAGLE_WLAN_IRQ_GPIO, OMAP_PIN_INPUT_PULLUP);
+
+		/* WLAN SDIO: MMC2 CLK */
+		omap_mux_init_signal("sdmmc2_clk.sdmmc2_clk", OMAP_PIN_INPUT_PULLUP);
+
+		/* WLAN SDIO: MMC2 CMD */
+		omap_mux_init_signal("sdmmc2_cmd.sdmmc2_cmd", OMAP_PIN_INPUT_PULLUP);
+
+		/* WLAN SDIO: MMC2 DAT[0-3] */
+		omap_mux_init_signal("sdmmc2_dat0.sdmmc2_dat0", OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("sdmmc2_dat1.sdmmc2_dat1", OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("sdmmc2_dat2.sdmmc2_dat2", OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("sdmmc2_dat3.sdmmc2_dat3", OMAP_PIN_INPUT_PULLUP);
+
+		expansion_config.mmc_settings = EXPANSION_MMC_WIFI;
+	#endif
+	}
+
+	if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
+	{
+		int r;
+		expansion_config.i2c_settings = EXPANSION_I2C_7ULCD;
+
+		/* TODO: set lcd_driver_name by command line or device tree */
+		beagle_config.lcd_driver_name = "tfc_s9700rtwv35tr-01b",
+		lcd_panel.name = beagle_config.lcd_driver_name;
+
+		r = gpio_request_one(beagle_config.lcd_pwren, GPIOF_OUT_INIT_LOW, "LCD power");
+		if (r < 0)
+			pr_err("Beagle expansionboard: Unable to get LCD power enable GPIO\n");
+	}
+
 	if (gpio_is_valid(beagle_config.mmc1_gpio_wp))
 		omap_mux_init_gpio(beagle_config.mmc1_gpio_wp, OMAP_PIN_INPUT);
-	mmc[0].caps = beagle_config.mmc_caps;
-	omap_hsmmc_init(mmc);
+
+	switch (expansion_config.mmc_settings) {
+	case EXPANSION_MMC_WIFI:
+		mmcbbt[0].caps = beagle_config.mmc_caps;
+		omap_hsmmc_init(mmcbbt);
+		break;
+	case EXPANSION_MMC_ZIPPY:
+		mmc_zippy[0].caps = beagle_config.mmc_caps;
+		omap_hsmmc_init(mmc_zippy);
+		break;
+	default:
+		mmc[0].caps = beagle_config.mmc_caps;
+		omap_hsmmc_init(mmc);
+	}
 
 	omap3_beagle_i2c_init();
 
@@ -519,6 +1172,103 @@ static void __init omap3_beagle_init(void)
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
 
+	if (!strcmp(expansionboard_name, "zippy"))
+	{
+		pr_info("Beagle expansionboard: initializing enc28j60\n");
+		omap3beagle_enc28j60_init();
+	}
+
+	if (!strcmp(expansionboard_name, "zippy2"))
+	{
+		pr_info("Beagle expansionboard: initializing ks_8851\n");
+		omap3beagle_ks8851_init();
+	}
+
+	if (!strcmp(expansionboard_name, "trainer"))
+	{
+		pr_info("Beagle expansionboard: exporting GPIOs 130-141,162 to userspace\n");
+		gpio_request(130, "sysfs");
+		gpio_export(130, 1);
+		gpio_request(131, "sysfs");
+		gpio_export(131, 1);
+		gpio_request(132, "sysfs");
+		gpio_export(132, 1);
+		gpio_request(133, "sysfs");
+		gpio_export(133, 1);
+		gpio_request(134, "sysfs");
+		gpio_export(134, 1);
+		gpio_request(135, "sysfs");
+		gpio_export(135, 1);
+		gpio_request(136, "sysfs");
+		gpio_export(136, 1);
+		gpio_request(137, "sysfs");
+		gpio_export(137, 1);
+		gpio_request(138, "sysfs");
+		gpio_export(138, 1);
+		gpio_request(139, "sysfs");
+		gpio_export(139, 1);
+		gpio_request(140, "sysfs");
+		gpio_export(140, 1);
+		gpio_request(141, "sysfs");
+		gpio_export(141, 1);
+		gpio_request(162, "sysfs");
+		gpio_export(162, 1);
+	}
+
+	if ((!strcmp(expansionboard_name, "bbtoys-wifi")) || (!strcmp(expansionboard_name, "lsr-com6l-adpt")))
+	{
+	#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
+		pr_info("Beagle expansionboard: initializing wl12xx platform\n");
+
+		if (!strcmp(wl12xx_name, "wl12xx_26mhz")) {
+			pr_info("wl12xx: 26Mhz reference clock (TiWi5)\n");
+			omap_beagle_wlan_data_26mhz.irq = gpio_to_irq(OMAP_BEAGLE_WLAN_IRQ_GPIO);
+			if (wl12xx_set_platform_data(&omap_beagle_wlan_data_26mhz))
+				pr_err("error setting wl12xx data\n");
+		} else {
+			pr_info("wl12xx: 38.4Mhz reference clock (TiWi2/TiWi-BLE)\n");
+			pr_info("wl12xx: for (TiWi5) support pass kernel [wl12xx_clk=wl12xx_26mhz]\n");
+			omap_beagle_wlan_data.irq = gpio_to_irq(OMAP_BEAGLE_WLAN_IRQ_GPIO);
+			if (wl12xx_set_platform_data(&omap_beagle_wlan_data))
+				pr_err("error setting wl12xx data\n");
+		}
+
+		pr_info("Beagle expansionboard: registering wl12xx bt platform device\n");
+		platform_device_register(&wl12xx_device);
+		platform_device_register(&btwilink_device);
+		pr_info("Beagle expansionboard: registering wl12xx wifi platform device\n");
+		platform_device_register(&omap_vwlan_device);
+	#endif
+	}
+
+	if (!strcmp(expansionboard_name, "beaglefpga"))
+	{
+		pr_info("Beagle expansionboard: enabling SPIdev for McSPI3/4 and pin muxing for McBSP3 slave mode\n");
+
+		/* FPGA pin settings configure McSPI 3, McSPI 4 and McBSP 3 */
+		omap3_beagle_config_fpga_mux();
+
+		/* register McSPI 3 and McSPI 4 for FPGA programming and control */
+		spi_register_board_info(beagle_mcspi_board_info, ARRAY_SIZE(beagle_mcspi_board_info));
+	}
+
+	if (!strcmp(expansionboard_name, "spidev"))
+	{
+		pr_info("Beagle expansionboard: registering spidev\n");
+		omap3_beagle_config_mcspi3_mux();
+		omap3_beagle_config_mcspi4_mux();
+		spi_register_board_info(beagle_mcspi_board_info, ARRAY_SIZE(beagle_mcspi_board_info));
+	}
+
+	if (!strcmp(expansionboard2_name, "bbtoys-ulcd"))
+	{
+	#if defined(CONFIG_TOUCHSCREEN_TSC2007) || defined(CONFIG_TOUCHSCREEN_TSC2007_MODULE)
+		pr_info("Beagle expansionboard: initializing touchscreen: tsc2007\n");
+		omap3beagle_tsc2007_init();
+	#endif
+	}
+
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	board_nand_init(omap3beagle_nand_partitions,
@@ -534,6 +1284,44 @@ static void __init omap3_beagle_init(void)
 	omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
 }
 
+static int __init omap3_beagle_late_initcall(void)
+{
+	if (!machine_is_omap3_beagle())
+		return 0;
+
+	if (!cpu_is_omap3630())
+		return 0;
+
+#if defined(CONFIG_VIDEO_MT9P031)
+	if ((!strcmp(camera_name, "lbcm5m1")) || (!strcmp(camera_name, "li5m03")))
+	{
+		pr_info("Beagle camera: MT9P031 init\n");
+
+		reg_1v8 = regulator_get(NULL, "cam_1v8");
+		if (IS_ERR(reg_1v8))
+			pr_err("%s: cannot get cam_1v8 regulator\n", __func__);
+		else
+			regulator_enable(reg_1v8);
+
+		reg_2v8 = regulator_get(NULL, "cam_2v8");
+		if (IS_ERR(reg_2v8))
+			pr_err("%s: cannot get cam_2v8 regulator\n", __func__);
+		else
+			regulator_enable(reg_2v8);
+
+		omap3_init_camera(&beagle_isp_platform_data);
+	}
+#endif
+	return 0;
+}
+
+early_param("buddy", expansionboard_setup);
+early_param("buddy2", expansionboard2_setup);
+early_param("camera", camera_setup);
+early_param("wl12xx_clk", wl12xx_setup);
+
+late_initcall(omap3_beagle_late_initcall);
+
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
 	/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
 	.atag_offset	= 0x100,
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 3985f35..a198b61 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -41,6 +41,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/mmc/host.h>
 #include <linux/export.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -734,6 +735,7 @@ static void __init omap3_evm_init(void)
 		omap_mux_init_gpio(135, OMAP_PIN_OUTPUT);
 		usbhs_bdata.reset_gpio_port[1] = 135;
 	}
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(&musb_board_data);
 	usbhs_init(&usbhs_bdata);
 	board_nand_init(omap3evm_nand_partitions,
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 2a065ba..9409eb8 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -29,6 +29,7 @@
 
 #include <linux/i2c/twl.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -215,6 +216,7 @@ static void __init omap3logic_init(void)
 	board_mmc_init();
 	board_smsc911x_init();
 
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index a53a668..1ac3e81 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -35,6 +35,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
 #include <linux/regulator/fixed.h>
+#include <linux/usb/phy.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
 #include <asm/mach-types.h>
@@ -601,6 +602,7 @@ static void __init omap3pandora_init(void)
 			ARRAY_SIZE(omap3pandora_spi_board_info));
 	omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
 	usbhs_init(&usbhs_bdata);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	gpmc_nand_init(&pandora_nand_data, NULL);
 
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 53a6cbc..63cb204 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -33,6 +33,7 @@
 #include <linux/interrupt.h>
 #include <linux/smsc911x.h>
 #include <linux/i2c/at24.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -404,6 +405,7 @@ static void __init omap3_stalker_init(void)
 
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	omap_ads7846_init(1, OMAP3_STALKER_TS_GPIO, 310, NULL);
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 263cb9c..6b22ce3 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -28,6 +28,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/spi/spi.h>
@@ -365,6 +366,7 @@ static void __init omap3_touchbook_init(void)
 
 	/* Touchscreen and accelerometer */
 	omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	board_nand_init(omap3touchbook_nand_partitions,
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 769c1fe..40184cc 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -30,6 +30,7 @@
 #include <linux/regulator/fixed.h>
 #include <linux/ti_wilink_st.h>
 #include <linux/usb/musb.h>
+#include <linux/usb/phy.h>
 #include <linux/wl12xx.h>
 #include <linux/platform_data/omap-abe-twl6040.h>
 
@@ -447,6 +448,7 @@ static void __init omap4_panda_init(void)
 	omap_sdrc_init(NULL, NULL);
 	omap4_twl6030_hsmmc_init(mmc);
 	omap4_ehci_init();
+	usb_bind_phy("musb-hdrc.0.auto", 0, "omap-usb2.1.auto");
 	usb_musb_init(&musb_board_data);
 	omap4_panda_display_init();
 }
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index c8fde3e..7e43ff3 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -36,6 +36,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mmc/host.h>
+#include <linux/usb/phy.h>
 
 #include <linux/platform_data/mtd-nand-omap2.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
@@ -499,6 +500,7 @@ static void __init overo_init(void)
 				  mt46h32m32lf6_sdrc_params);
 	board_nand_init(overo_nand_partitions,
 			ARRAY_SIZE(overo_nand_partitions), NAND_CS, 0, NULL);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 0c777b7..f8a272c 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -18,6 +18,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/consumer.h>
 #include <linux/platform_data/mtd-onenand-omap2.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -134,6 +135,7 @@ static void __init rm680_init(void)
 	sdrc_params = nokia_get_sdram_timings();
 	omap_sdrc_init(sdrc_params, sdrc_params);
 
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	rm680_peripherals_init();
 }
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 26e07ad..dc5498b 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -20,6 +20,7 @@
 #include <linux/wl12xx.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_data/gpio-omap.h>
+#include <linux/usb/phy.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -298,6 +299,7 @@ void __init zoom_peripherals_init(void)
 	omap_hsmmc_init(mmc);
 	omap_i2c_init();
 	platform_device_register(&omap_vwlan_device);
+	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	enable_board_wakeup_source();
 	omap_serial_init();
diff --git a/arch/arm/mach-omap2/cclock2430_data.c b/arch/arm/mach-omap2/cclock2430_data.c
index eb3dab6..89f6ed8 100644
--- a/arch/arm/mach-omap2/cclock2430_data.c
+++ b/arch/arm/mach-omap2/cclock2430_data.c
@@ -1992,9 +1992,11 @@ static struct omap_clk omap2430_clks[] = {
 	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(NULL,	"sha_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("omap-aes",	"ick",		&aes_ick,	CK_243X),
+	CLK(NULL,	"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),
diff --git a/arch/arm/mach-omap2/cclock33xx_data.c b/arch/arm/mach-omap2/cclock33xx_data.c
index ea64ad6..c028220 100644
--- a/arch/arm/mach-omap2/cclock33xx_data.c
+++ b/arch/arm/mach-omap2/cclock33xx_data.c
@@ -284,9 +284,10 @@ 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);
+DEFINE_CLK_DIVIDER(dpll_disp_m2_ck, "dpll_disp_ck", &dpll_disp_ck,
+		   CLK_SET_RATE_PARENT, 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 = {
@@ -412,6 +413,14 @@ 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);
 
+static struct clk sha0_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(sha0_fck, NULL);
+DEFINE_STRUCT_CLK(sha0_fck, dpll_core_ck_parents, clk_ops_null);
+
+static struct clk aes0_fck;
+DEFINE_STRUCT_CLK_HW_OMAP(aes0_fck, NULL);
+DEFINE_STRUCT_CLK(aes0_fck, dpll_core_ck_parents, clk_ops_null);
+
 /*
  * Modules clock nodes
  *
@@ -428,7 +437,7 @@ DEFINE_STRUCT_CLK(smartreflex1_fck, dpll_core_ck_parents, clk_ops_null);
  *     - 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,
+DEFINE_CLK_GATE(debugss_ick, "dpll_core_m4_ck", &dpll_core_m4_ck, ENABLE_ON_INIT,
 		AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT,
 		0x0, NULL);
 
@@ -723,7 +732,8 @@ static struct clk_hw_omap lcd_gclk_hw = {
 	.clksel_mask	= AM33XX_CLKSEL_0_1_MASK,
 };
 
-DEFINE_STRUCT_CLK(lcd_gclk, lcd_ck_parents, gpio_fck_ops);
+DEFINE_STRUCT_CLK_FLAGS(lcd_gclk, lcd_ck_parents,
+			gpio_fck_ops, CLK_SET_RATE_PARENT);
 
 DEFINE_CLK_FIXED_FACTOR(mmc_clk, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0, 1, 2);
 
@@ -808,6 +818,242 @@ DEFINE_CLK_DIVIDER_TABLE(clkout2_div_ck, "sysclkout_pre_ck", &sysclkout_pre_ck,
 DEFINE_CLK_GATE(clkout2_ck, "clkout2_div_ck", &clkout2_div_ck, 0x0,
 		AM33XX_CM_CLKOUT_CTRL, AM33XX_CLKOUT2EN_SHIFT, 0x0, NULL);
 
+/********************************************/
+
+static const char *adjustable_sysclkout_ck_parents[] = {
+	"clk_32768_ck", "l3_gclk", "dpll_ddr_m2_ck", "dpll_per_m2_ck",
+	"lcd_gclk",
+};
+
+static const struct clksel foo_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 },
+};
+
+struct clkout_match {
+	unsigned long best_rate;
+	unsigned long parent_rate;
+	const struct clksel *best_clks;
+	const struct clksel_rate *best_clkr;
+	const struct clk_div_table *best_clkd;
+};
+
+struct clk_hw_clkout {
+	struct clk_hw_omap		omap_hw;
+	void __iomem			*div_reg;
+	u32				div_mask;
+	const struct clk_div_table	*div_table;
+	struct clkout_match		match;
+};
+
+#define to_clk_hw_clkout(_hw) container_of(_hw, struct clk_hw_clkout, omap_hw.hw)
+
+static int clkout_clk_enable(struct clk_hw *hw)
+{
+	return omap2_dflt_clk_enable(hw);
+}
+
+static void clkout_clk_disable(struct clk_hw *hw)
+{
+	omap2_dflt_clk_enable(hw);
+}
+
+static int clkout_clk_is_enabled(struct clk_hw *hw)
+{
+	return omap2_dflt_clk_is_enabled(hw);
+}
+
+static int clkout_find_match(struct clk_hw *hw, unsigned long target_rate,
+		struct clkout_match *m)
+{
+	struct clk_hw_clkout *clkout_clk = to_clk_hw_clkout(hw);
+	struct clk_hw_omap *omap_clk = to_clk_hw_omap(hw);
+	struct clk *pclk;
+	unsigned long prate, test_rate;
+	const struct clksel *clks;
+	const struct clksel_rate *clkr;
+	const struct clk_div_table *clkd;
+
+	memset(m, 0, sizeof(*m));
+
+	/* iterate over all the clksel */
+	for (clks = omap_clk->clksel; (pclk = clks->parent) != NULL; clks++) {
+		prate = __clk_get_rate(pclk);
+		for (clkr = clks->rates; clkr->div; clkr++) {
+			if (!(clkr->flags & cpu_mask))
+				continue;
+			for (clkd = clkout_clk->div_table; clkd->div; clkd++) {
+				test_rate = (prate / clkr->div) / clkd->div;
+
+				if (abs(test_rate - target_rate) < abs(m->best_rate - target_rate)) {
+					m->parent_rate = prate / clkr->div;
+					m->best_rate = test_rate;
+					m->best_clks = clks;
+					m->best_clkr = clkr;
+					m->best_clkd = clkd;
+				}
+			}
+		}
+	}
+
+	if (!m->best_clks || !m->best_clkr || !m->best_clkd) {
+		pr_err("%s: Failed to find a best match\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int clkout_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clk_hw_clkout *clkout_clk = to_clk_hw_clkout(hw);
+	struct clk_hw_omap *omap_clk = to_clk_hw_omap(hw);
+	struct clkout_match *m = &clkout_clk->match;
+	struct clk *clk = hw->clk;
+	int ret;
+	u32 v;
+
+	ret = clkout_find_match(hw, rate, m);
+	if (ret != 0)
+		return ret;
+
+	/* have to be exact now */
+	if (rate != m->best_rate) {
+		pr_err("%s: Failed to find exact rate %lu (was %lu)\n",
+				__func__, rate, m->best_rate);
+		return -EINVAL;
+	}
+
+	/* switch parent */
+	if (m->best_clks->parent != __clk_get_parent(clk)) {
+		__clk_set_parent(clk, m->best_clks->parent);
+		__clk_reparent(clk, m->best_clks->parent);
+		parent_rate = __clk_get_rate(__clk_get_parent(clk));
+	}
+
+	/* we need to write the new value */
+	if (omap_clk->clksel_reg != clkout_clk->div_reg) {
+		v = __raw_readl(omap_clk->clksel_reg);
+		v &= ~omap_clk->clksel_mask;
+		v |= m->best_clkr->val << __ffs(omap_clk->clksel_mask);
+		__raw_writel(v, omap_clk->clksel_reg);
+		v = __raw_readl(omap_clk->clksel_reg);	/* OCP barrier */
+
+		v = __raw_readl(clkout_clk->div_reg);
+		v &= ~clkout_clk->div_mask;
+		v |= m->best_clkd->val << __ffs(clkout_clk->div_mask);
+		__raw_writel(v, clkout_clk->div_reg);
+		v = __raw_readl(clkout_clk->div_reg);	/* OCP barrier */
+	} else {
+		v = __raw_readl(omap_clk->clksel_reg);
+		v &= ~(omap_clk->clksel_mask | clkout_clk->div_mask);
+		v |= (m->best_clkr->val << __ffs(omap_clk->clksel_mask)) |
+		     (m->best_clkd->val << __ffs(clkout_clk->div_mask));
+		__raw_writel(v, omap_clk->clksel_reg);
+		v = __raw_readl(omap_clk->clksel_reg);	/* OCP barrier */
+	}
+
+	return ret;
+}
+
+static long clkout_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
+				unsigned long *parent_rate)
+{
+	struct clkout_match m;
+	long ret;
+
+	ret = clkout_find_match(hw, target_rate, &m);
+	if (ret != 0) {
+		pr_err("%s: Failed to find a best match\n", __func__);
+		return (unsigned long)-1;
+	}
+
+	*parent_rate = __clk_get_rate(m.best_clks->parent);
+
+	return m.best_rate;
+}
+
+static unsigned long clkout_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct clk_hw_clkout *clkout_clk = to_clk_hw_clkout(hw);
+	struct clk_hw_omap *omap_clk = to_clk_hw_omap(hw);
+	u32 v;
+	unsigned int divr, divd;
+
+	v = __raw_readl(omap_clk->clksel_reg);
+	v &= omap_clk->clksel_mask;
+	v >>= __ffs(omap_clk->clksel_mask);
+	divr = v;
+
+	v = __raw_readl(clkout_clk->div_reg);
+	v &= clkout_clk->div_mask;
+	v >>= __ffs(clkout_clk->div_mask);
+	divd = v;
+
+	return clkout_clk->match.best_rate;
+}
+
+static u8 clkout_clksel_find_parent_index(struct clk_hw *hw)
+{
+	return omap2_clksel_find_parent_index(hw);
+}
+
+static int clkout_clksel_set_parent(struct clk_hw *hw, u8 field_val)
+{
+	return omap2_clksel_set_parent(hw, field_val);
+}
+
+static void clkout_init_clk_clkdm(struct clk_hw *hw)
+{
+	omap2_init_clk_clkdm(hw);
+}
+
+static const struct clk_ops adjustable_sysclkout_ck_clk_ops = {
+	.enable		= &clkout_clk_enable,
+	.disable	= &clkout_clk_disable,
+	.is_enabled	= &clkout_clk_is_enabled,
+	.set_rate	= &clkout_clksel_set_rate,
+	.round_rate	= &clkout_clksel_round_rate,
+	.recalc_rate	= &clkout_clksel_recalc,
+	.get_parent	= &clkout_clksel_find_parent_index,
+	.set_parent	= &clkout_clksel_set_parent,
+	.init		= &clkout_init_clk_clkdm,
+};
+
+static struct clk adjustable_clkout2_ck;
+static struct clk_hw_clkout adjustable_clkout2_ck_hw = {
+	.omap_hw = {
+		.hw = {
+			.clk	= &adjustable_clkout2_ck,
+		},
+		.ops		= NULL,
+		.enable_reg	= AM33XX_CM_CLKOUT_CTRL,
+		.enable_bit	= AM33XX_CLKOUT2EN_SHIFT,
+		.clksel		= foo_sysclkout_pre_sel,
+		.clksel_reg	= AM33XX_CM_CLKOUT_CTRL,
+		.clksel_mask	= AM33XX_CLKOUT2SOURCE_MASK,
+		.clkdm_name	= NULL,
+	},
+	.div_reg	= AM33XX_CM_CLKOUT_CTRL,
+	.div_mask	= AM33XX_CLKOUT2DIV_MASK,
+	.div_table	= div8_rates,
+};
+static struct clk adjustable_clkout2_ck = {
+	.name		= "adjustable_clkout2_ck",
+	.hw		= &adjustable_clkout2_ck_hw.omap_hw.hw,
+	.parent_names	= adjustable_sysclkout_ck_parents,
+	.num_parents	= ARRAY_SIZE(adjustable_sysclkout_ck_parents),
+	.ops		= &adjustable_sysclkout_ck_clk_ops,
+	.flags		= CLK_GET_RATE_NOCACHE | CLK_SET_PARENT_GATE | CLK_SET_RATE_GATE
+};
+
+/********************************************/
+
 static const char *wdt_ck_parents[] = {
 	"clk_rc32k_ck", "clkdiv32k_ick",
 };
@@ -832,6 +1078,33 @@ static struct clk_hw_omap wdt1_fck_hw = {
 
 DEFINE_STRUCT_CLK(wdt1_fck, wdt_ck_parents, gpio_fck_ops);
 
+static const char *pwmss_clk_parents[] = {
+	"dpll_per_m2_ck",
+};
+
+static const struct clk_ops ehrpwm_tbclk_ops = {
+	.enable		= &omap2_dflt_clk_enable,
+	.disable	= &omap2_dflt_clk_disable,
+};
+
+DEFINE_CLK_OMAP_MUX_GATE(ehrpwm0_tbclk, "l4ls_clkdm",
+			 0, NULL, 0,
+			 AM33XX_CTRL_REGADDR(AM33XX_PWMSS_TBCLK_CLKCTRL),
+			 AM33XX_PWMSS0_TBCLKEN_SHIFT,
+			 NULL, pwmss_clk_parents, ehrpwm_tbclk_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(ehrpwm1_tbclk, "l4ls_clkdm",
+			 0, NULL, 0,
+			 AM33XX_CTRL_REGADDR(AM33XX_PWMSS_TBCLK_CLKCTRL),
+			 AM33XX_PWMSS1_TBCLKEN_SHIFT,
+			 NULL, pwmss_clk_parents, ehrpwm_tbclk_ops);
+
+DEFINE_CLK_OMAP_MUX_GATE(ehrpwm2_tbclk, "l4ls_clkdm",
+			 0, NULL, 0,
+			 AM33XX_CTRL_REGADDR(AM33XX_PWMSS_TBCLK_CLKCTRL),
+			 AM33XX_PWMSS2_TBCLKEN_SHIFT,
+			 NULL, pwmss_clk_parents, ehrpwm_tbclk_ops);
+
 /*
  * clkdev
  */
@@ -876,6 +1149,8 @@ static struct omap_clk am33xx_clks[] = {
 	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,	"sha0_fck",		&sha0_fck,	CK_AM33XX),
+	CLK(NULL,	"aes0_fck",		&aes0_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),
@@ -908,8 +1183,15 @@ static struct omap_clk am33xx_clks[] = {
 	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,	"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),
+	CLK("48300200.ehrpwm",	"tbclk",	&ehrpwm0_tbclk,	CK_AM33XX),
+	CLK("48302200.ehrpwm",	"tbclk",	&ehrpwm1_tbclk,	CK_AM33XX),
+	CLK("48304200.ehrpwm",	"tbclk",	&ehrpwm2_tbclk,	CK_AM33XX),
+	CLK("4830e000.fb", 	"fck",		&lcd_gclk,	CK_AM33XX),
+	/* magical adjustable clkout2 without mult/div */
+	CLK(NULL,	"adjustable_clkout2_ck",	&adjustable_clkout2_ck,CK_AM33XX),
 };
 
 
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
index 6ef8758..6cbd801 100644
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -3334,8 +3334,10 @@ static struct omap_clk omap3xxx_clks[] = {
 	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-aes",	"ick",		&aes2_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"aes2_ick",	&aes2_ick,	CK_34XX | CK_36XX),
 	CLK("omap-sham",	"ick",	&sha12_ick,	CK_34XX | CK_36XX),
+	CLK(NULL,	"sha12_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),
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
index 924c230..15e6d41 100644
--- a/arch/arm/mach-omap2/clkt_dpll.c
+++ b/arch/arm/mach-omap2/clkt_dpll.c
@@ -345,20 +345,22 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 		pr_debug("clock: %s: m = %d: n = %d: new_rate = %ld\n",
 			 clk_name, m, n, new_rate);
 
-		if (target_rate == new_rate) {
+		if ((new_rate <= target_rate) &&
+		    (new_rate > dd->last_rounded_rate)) {
 			dd->last_rounded_m = m;
 			dd->last_rounded_n = n;
-			dd->last_rounded_rate = target_rate;
-			break;
+			dd->last_rounded_rate = new_rate;
+			if (new_rate == target_rate)
+				break;
 		}
 	}
 
-	if (target_rate != new_rate) {
+	if (!dd->last_rounded_rate) {
 		pr_debug("clock: %s: cannot round to rate %ld\n",
 			 clk_name, target_rate);
 		return ~0;
 	}
 
-	return target_rate;
+	return dd->last_rounded_rate;
 }
 
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index b402048..60ddd86 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -65,6 +65,17 @@ struct clockdomain;
 		.ops = &_clkops_name,				\
 	};
 
+#define DEFINE_STRUCT_CLK_FLAGS(_name, _parent_array_name,	\
+				_clkops_name, _flags)		\
+	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,				\
+		.flags = _flags,				\
+	};
+
 #define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name)		\
 	static struct clk_hw_omap _name##_hw = {		\
 		.hw = {						\
diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c
index 058ce3c..325a515 100644
--- a/arch/arm/mach-omap2/cm33xx.c
+++ b/arch/arm/mach-omap2/cm33xx.c
@@ -241,9 +241,6 @@ int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs)
 {
 	int i = 0;
 
-	if (!clkctrl_offs)
-		return 0;
-
 	omap_test_timeout(_is_module_ready(inst, cdoffs, clkctrl_offs),
 			  MAX_MODULE_READY_TIME, i);
 
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index b9adf69..f077fbd 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -119,6 +119,14 @@ static inline void omap2xxx_restart(char mode, const char *cmd)
 }
 #endif
 
+#ifdef CONFIG_SOC_AM33XX
+void am33xx_restart(char mode, const char *cmd);
+#else
+static inline void am33xx_restart(char mode, const char *cmd)
+{
+}
+#endif
+
 #ifdef CONFIG_ARCH_OMAP3
 void omap3xxx_restart(char mode, const char *cmd);
 #else
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index e6c3281..12d8468 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -352,12 +352,24 @@
 /* AM33XX CONTROL_STATUS register */
 #define AM33XX_CONTROL_STATUS		0x040
 #define AM33XX_CONTROL_SEC_CLK_CTRL	0x1bc
+#define AM33XX_CONTROL_MAC_ID0_LOW	0x630
+#define AM33XX_CONTROL_MAC_ID0_HIGH	0x634
+#define AM33XX_CONTROL_MAC_ID1_LOW	0x638
+#define AM33XX_CONTROL_MAC_ID1_HIGH	0x63c
 
 /* AM33XX CONTROL_STATUS bitfields (partial) */
 #define AM33XX_CONTROL_STATUS_SYSBOOT1_SHIFT		22
 #define AM33XX_CONTROL_STATUS_SYSBOOT1_WIDTH		0x2
 #define AM33XX_CONTROL_STATUS_SYSBOOT1_MASK		(0x3 << 22)
 
+/* AM33XX PWMSS Control register */
+#define AM33XX_PWMSS_TBCLK_CLKCTRL			0x664
+
+/* AM33XX  PWMSS Control bitfields */
+#define AM33XX_PWMSS0_TBCLKEN_SHIFT			0
+#define AM33XX_PWMSS1_TBCLKEN_SHIFT			1
+#define AM33XX_PWMSS2_TBCLKEN_SHIFT			2
+
 /* CONTROL OMAP STATUS register to identify OMAP3 features */
 #define OMAP3_CONTROL_OMAP_STATUS	0x044c
 
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 626f3ea..a6d8070 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -446,6 +446,20 @@ static void omap_init_mcspi(void)
 static inline void omap_init_mcspi(void) {}
 #endif
 
+#include "cm33xx.h"
+
+int __init am33xx_register_ehrpwm(void)
+{
+	void __iomem *iobase;
+	unsigned short regword;
+
+	iobase = AM33XX_CM_REGADDR(0, 0x10664);
+	regword = readw(iobase);
+	regword |= 0x7;
+	writew(regword, iobase);
+	return 0;
+}
+
 /**
  * omap_init_rng - bind the RNG hwmod to the RNG omap_device
  *
@@ -464,140 +478,31 @@ static void omap_init_rng(void)
 	WARN(IS_ERR(pdev), "Can't build omap_device for omap_rng\n");
 }
 
-#if defined(CONFIG_CRYPTO_DEV_OMAP_SHAM) || defined(CONFIG_CRYPTO_DEV_OMAP_SHAM_MODULE)
-
-#ifdef CONFIG_ARCH_OMAP2
-static struct resource omap2_sham_resources[] = {
-	{
-		.start	= OMAP24XX_SEC_SHA1MD5_BASE,
-		.end	= OMAP24XX_SEC_SHA1MD5_BASE + 0x64,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= 51 + OMAP_INTC_START,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-static int omap2_sham_resources_sz = ARRAY_SIZE(omap2_sham_resources);
-#else
-#define omap2_sham_resources		NULL
-#define omap2_sham_resources_sz		0
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-static struct resource omap3_sham_resources[] = {
-	{
-		.start	= OMAP34XX_SEC_SHA1MD5_BASE,
-		.end	= OMAP34XX_SEC_SHA1MD5_BASE + 0x64,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= 49 + OMAP_INTC_START,
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
-		.start	= OMAP34XX_DMA_SHA1MD5_RX,
-		.flags	= IORESOURCE_DMA,
-	}
-};
-static int omap3_sham_resources_sz = ARRAY_SIZE(omap3_sham_resources);
-#else
-#define omap3_sham_resources		NULL
-#define omap3_sham_resources_sz		0
-#endif
-
-static struct platform_device sham_device = {
-	.name		= "omap-sham",
-	.id		= -1,
-};
-
-static void omap_init_sham(void)
+static void __init omap_init_sham(void)
 {
-	if (cpu_is_omap24xx()) {
-		sham_device.resource = omap2_sham_resources;
-		sham_device.num_resources = omap2_sham_resources_sz;
-	} else if (cpu_is_omap34xx()) {
-		sham_device.resource = omap3_sham_resources;
-		sham_device.num_resources = omap3_sham_resources_sz;
-	} else {
-		pr_err("%s: platform not supported\n", __func__);
-		return;
-	}
-	platform_device_register(&sham_device);
-}
-#else
-static inline void omap_init_sham(void) { }
-#endif
-
-#if defined(CONFIG_CRYPTO_DEV_OMAP_AES) || defined(CONFIG_CRYPTO_DEV_OMAP_AES_MODULE)
-
-#ifdef CONFIG_ARCH_OMAP2
-static struct resource omap2_aes_resources[] = {
-	{
-		.start	= OMAP24XX_SEC_AES_BASE,
-		.end	= OMAP24XX_SEC_AES_BASE + 0x4C,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= OMAP24XX_DMA_AES_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	{
-		.start	= OMAP24XX_DMA_AES_RX,
-		.flags	= IORESOURCE_DMA,
-	}
-};
-static int omap2_aes_resources_sz = ARRAY_SIZE(omap2_aes_resources);
-#else
-#define omap2_aes_resources		NULL
-#define omap2_aes_resources_sz		0
-#endif
+	struct omap_hwmod *oh;
+	struct platform_device *pdev;
 
-#ifdef CONFIG_ARCH_OMAP3
-static struct resource omap3_aes_resources[] = {
-	{
-		.start	= OMAP34XX_SEC_AES_BASE,
-		.end	= OMAP34XX_SEC_AES_BASE + 0x4C,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= OMAP34XX_DMA_AES2_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	{
-		.start	= OMAP34XX_DMA_AES2_RX,
-		.flags	= IORESOURCE_DMA,
-	}
-};
-static int omap3_aes_resources_sz = ARRAY_SIZE(omap3_aes_resources);
-#else
-#define omap3_aes_resources		NULL
-#define omap3_aes_resources_sz		0
-#endif
+	oh = omap_hwmod_lookup("sham");
+	if (!oh)
+		return;
 
-static struct platform_device aes_device = {
-	.name		= "omap-aes",
-	.id		= -1,
-};
+	pdev = omap_device_build("omap-sham", -1, oh, NULL, 0, NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Can't build omap_device for omap-sham\n");
+}
 
-static void omap_init_aes(void)
+static void __init omap_init_aes(void)
 {
-	if (cpu_is_omap24xx()) {
-		aes_device.resource = omap2_aes_resources;
-		aes_device.num_resources = omap2_aes_resources_sz;
-	} else if (cpu_is_omap34xx()) {
-		aes_device.resource = omap3_aes_resources;
-		aes_device.num_resources = omap3_aes_resources_sz;
-	} else {
-		pr_err("%s: platform not supported\n", __func__);
+	struct omap_hwmod *oh;
+	struct platform_device *pdev;
+
+	oh = omap_hwmod_lookup("aes");
+	if (!oh)
 		return;
-	}
-	platform_device_register(&aes_device);
-}
 
-#else
-static inline void omap_init_aes(void) { }
-#endif
+	pdev = omap_device_build("omap-aes", -1, oh, NULL, 0, NULL, 0, 0);
+	WARN(IS_ERR(pdev), "Can't build omap_device for omap-aes\n");
+}
 
 /*-------------------------------------------------------------------------*/
 
@@ -724,14 +629,16 @@ static int __init omap2_init_devices(void)
 		omap_init_dmic();
 		omap_init_mcpdm();
 		omap_init_mcspi();
+		omap_init_sham();
+		omap_init_aes();
 	}
 	omap_init_sti();
 	omap_init_rng();
-	omap_init_sham();
-	omap_init_aes();
 	omap_init_vout();
 	omap_init_ocp2scp();
-
+	if (soc_is_am33xx()) {
+		am33xx_register_ehrpwm();
+	}
 	return 0;
 }
 arch_initcall(omap2_init_devices);
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 0a02aab5..3aed4b0 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -500,8 +500,9 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
 		if (dd->last_rounded_rate == 0)
 			return -EINVAL;
 
-		/* No freqsel on OMAP4 and OMAP3630 */
-		if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
+		/* No freqsel on AM335x, OMAP4 and OMAP3630 */
+		if (!soc_is_am33xx() && !cpu_is_omap44xx() &&
+		    !cpu_is_omap3630()) {
 			freqsel = _omap3_dpll_compute_freqsel(clk,
 						dd->last_rounded_n);
 			WARN_ON(!freqsel);
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index db969a5..d9c2719 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -74,14 +74,6 @@ static int omap2_nand_gpmc_retime(
 	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)
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
-	else
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
-	gpmc_cs_configure(gpmc_nand_data->cs,
-			GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
-	gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_WP, 0);
 	err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
 	if (err)
 		return err;
@@ -89,20 +81,21 @@ static int omap2_nand_gpmc_retime(
 	return 0;
 }
 
-static bool __init gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
+static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
 {
 	/* support only OMAP3 class */
-	if (!cpu_is_omap34xx()) {
+	if (!cpu_is_omap34xx() && !soc_is_am33xx()) {
 		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.
+	 * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1
+	 * and AM33xx derivates. Other chips may be added if confirmed to work.
 	 */
 	if ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) &&
-	    (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) {
+	    (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0)) &&
+	    (!soc_is_am33xx())) {
 		pr_err("BCH 4-bit mode is not supported on this CPU\n");
 		return 0;
 	}
@@ -110,18 +103,22 @@ static bool __init gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
 	return 1;
 }
 
-int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
-			  struct gpmc_timings *gpmc_t)
+int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
+		   struct gpmc_timings *gpmc_t)
 {
 	int err	= 0;
+	struct gpmc_settings s;
 	struct device *dev = &gpmc_nand_device.dev;
 
+	memset(&s, 0, sizeof(struct gpmc_settings));
+
 	gpmc_nand_device.dev.platform_data = gpmc_nand_data;
 
 	err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
 				(unsigned long *)&gpmc_nand_resource[0].start);
 	if (err < 0) {
-		dev_err(dev, "Cannot request GPMC CS\n");
+		dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
+			gpmc_nand_data->cs, err);
 		return err;
 	}
 
@@ -139,11 +136,31 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
 			dev_err(dev, "Unable to set gpmc timings: %d\n", err);
 			return err;
 		}
-	}
 
-	/* Enable RD PIN Monitoring Reg */
-	if (gpmc_nand_data->dev_ready) {
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
+		if (gpmc_nand_data->of_node) {
+			gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
+		} else {
+			s.device_nand = true;
+
+			/* Enable RD PIN Monitoring Reg */
+			if (gpmc_nand_data->dev_ready) {
+				s.wait_on_read = true;
+				s.wait_on_write = true;
+			}
+		}
+
+		if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
+			s.device_width = GPMC_DEVWIDTH_16BIT;
+		else
+			s.device_width = GPMC_DEVWIDTH_8BIT;
+
+		err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s);
+		if (err < 0)
+			goto out_free_cs;
+
+		err = gpmc_configure(GPMC_CONFIG_WP, 0);
+		if (err < 0)
+			goto out_free_cs;
 	}
 
 	gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 94a349e..64b5a83 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -47,11 +47,23 @@ static struct platform_device gpmc_onenand_device = {
 	.resource	= &gpmc_onenand_resource,
 };
 
-static struct gpmc_timings omap2_onenand_calc_async_timings(void)
+static struct gpmc_settings onenand_async = {
+	.device_width	= GPMC_DEVWIDTH_16BIT,
+	.mux_add_data	= GPMC_MUX_AD,
+};
+
+static struct gpmc_settings onenand_sync = {
+	.burst_read	= true,
+	.burst_wrap	= true,
+	.burst_len	= GPMC_BURST_16,
+	.device_width	= GPMC_DEVWIDTH_16BIT,
+	.mux_add_data	= GPMC_MUX_AD,
+	.wait_pin	= 0,
+};
+
+static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
 {
 	struct gpmc_device_timings dev_t;
-	struct gpmc_timings t;
-
 	const int t_cer = 15;
 	const int t_avdp = 12;
 	const int t_aavdh = 7;
@@ -64,7 +76,6 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void)
 
 	memset(&dev_t, 0, sizeof(dev_t));
 
-	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;
@@ -76,19 +87,7 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void)
 	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);
-
-	return gpmc_cs_set_timings(cs, t);
+	gpmc_calc_timings(t, &onenand_async, &dev_t);
 }
 
 static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
@@ -158,12 +157,11 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
 	return freq;
 }
 
-static struct gpmc_timings
-omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
-				int freq)
+static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t,
+					    unsigned int flags,
+					    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 */
@@ -172,9 +170,9 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
 	int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
 	int div, gpmc_clk_ns;
 
-	if (cfg->flags & ONENAND_SYNC_READ)
+	if (flags & ONENAND_SYNC_READ)
 		onenand_flags = ONENAND_FLAG_SYNCREAD;
-	else if (cfg->flags & ONENAND_SYNC_READWRITE)
+	else if (flags & ONENAND_SYNC_READWRITE)
 		onenand_flags = ONENAND_FLAG_SYNCREAD | ONENAND_FLAG_SYNCWRITE;
 
 	switch (freq) {
@@ -239,10 +237,11 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
 	/* Set synchronous read timings */
 	memset(&dev_t, 0, sizeof(dev_t));
 
-	dev_t.mux = true;
-	dev_t.sync_read = true;
+	if (onenand_flags & ONENAND_FLAG_SYNCREAD)
+		onenand_sync.sync_read = true;
 	if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
-		dev_t.sync_write = true;
+		onenand_sync.sync_write = true;
+		onenand_sync.burst_write = true;
 	} else {
 		dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000;
 		dev_t.t_wpl = t_wpl * 1000;
@@ -265,32 +264,7 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
 	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;
-}
-
-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,
-			  GPMC_CONFIG1_WRAPBURST_SUPP |
-			  GPMC_CONFIG1_READMULTIPLE_SUPP |
-			  (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
-			  (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
-			  (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
-			  GPMC_CONFIG1_PAGE_LEN(2) |
-			  (cpu_is_omap34xx() ? 0 :
-				(GPMC_CONFIG1_WAIT_READ_MON |
-				 GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
-			  GPMC_CONFIG1_DEVICESIZE_16 |
-			  GPMC_CONFIG1_DEVICETYPE_NOR |
-			  GPMC_CONFIG1_MUXADDDATA);
-
-	return gpmc_cs_set_timings(cs, t);
+	gpmc_calc_timings(t, &onenand_sync, &dev_t);
 }
 
 static int omap2_onenand_setup_async(void __iomem *onenand_base)
@@ -298,12 +272,20 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
 	struct gpmc_timings t;
 	int ret;
 
+	if (gpmc_onenand_data->of_node)
+		gpmc_read_settings_dt(gpmc_onenand_data->of_node,
+				      &onenand_async);
+
 	omap2_onenand_set_async_mode(onenand_base);
 
-	t = omap2_onenand_calc_async_timings();
+	omap2_onenand_calc_async_timings(&t);
+
+	ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async);
+	if (ret < 0)
+		return ret;
 
-	ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
-	if (IS_ERR_VALUE(ret))
+	ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
+	if (ret < 0)
 		return ret;
 
 	omap2_onenand_set_async_mode(onenand_base);
@@ -322,10 +304,26 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
 		set_onenand_cfg(onenand_base);
 	}
 
-	t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq);
+	if (gpmc_onenand_data->of_node) {
+		gpmc_read_settings_dt(gpmc_onenand_data->of_node,
+				      &onenand_sync);
+	} else {
+		/*
+		 * FIXME: Appears to be legacy code from initial ONENAND commit.
+		 * Unclear what boards this is for and if this can be removed.
+		 */
+		if (!cpu_is_omap34xx())
+			onenand_sync.wait_on_read = true;
+	}
+
+	omap2_onenand_calc_sync_timings(&t, gpmc_onenand_data->flags, freq);
 
-	ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
-	if (IS_ERR_VALUE(ret))
+	ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_sync);
+	if (ret < 0)
+		return ret;
+
+	ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
+	if (ret < 0)
 		return ret;
 
 	set_onenand_cfg(onenand_base);
@@ -356,9 +354,10 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 	return ret;
 }
 
-void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 {
 	int err;
+	struct device *dev = &gpmc_onenand_device.dev;
 
 	gpmc_onenand_data = _onenand_data;
 	gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
@@ -366,7 +365,7 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 
 	if (cpu_is_omap24xx() &&
 			(gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
-		printk(KERN_ERR "Onenand using only SYNC_READ on 24xx\n");
+		dev_warn(dev, "OneNAND using only SYNC_READ on 24xx\n");
 		gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE;
 		gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
 	}
@@ -379,7 +378,8 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 	err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
 				(unsigned long *)&gpmc_onenand_resource.start);
 	if (err < 0) {
-		pr_err("%s: Cannot request GPMC CS\n", __func__);
+		dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
+			gpmc_onenand_data->cs, err);
 		return;
 	}
 
@@ -387,7 +387,7 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 							ONENAND_IO_SIZE - 1;
 
 	if (platform_device_register(&gpmc_onenand_device) < 0) {
-		pr_err("%s: Unable to register OneNAND device\n", __func__);
+		dev_err(dev, "Unable to register OneNAND device\n");
 		gpmc_cs_free(gpmc_onenand_data->cs);
 		return;
 	}
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
index 11d0b75..61a0635 100644
--- a/arch/arm/mach-omap2/gpmc-smc91x.c
+++ b/arch/arm/mach-omap2/gpmc-smc91x.c
@@ -49,6 +49,10 @@ static struct platform_device gpmc_smc91x_device = {
 	.resource	= gpmc_smc91x_resources,
 };
 
+static struct gpmc_settings smc91x_settings = {
+	.device_width = GPMC_DEVWIDTH_16BIT,
+};
+
 /*
  * Set the gpmc timings for smc91c96. The timings are taken
  * from the data sheet available at:
@@ -67,18 +71,6 @@ static int smc91c96_gpmc_retime(void)
 	const int t7 = 5;	/* Figure 12.4 write */
 	const int t8 = 5;	/* Figure 12.4 write */
 	const int t20 = 185;	/* Figure 12.2 read and 12.4 write */
-	u32 l;
-
-	l = GPMC_CONFIG1_DEVICESIZE_16;
-	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
-		l |= GPMC_CONFIG1_MUXADDDATA;
-	if (gpmc_cfg->flags & GPMC_READ_MON)
-		l |= GPMC_CONFIG1_WAIT_READ_MON;
-	if (gpmc_cfg->flags & GPMC_WRITE_MON)
-		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
-	if (gpmc_cfg->wait_pin)
-		l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin);
-	gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l);
 
 	/*
 	 * FIXME: Calculate the address and data bus muxed timings.
@@ -104,7 +96,7 @@ static int smc91c96_gpmc_retime(void)
 	dev_t.t_cez_w = t4_w * 1000;
 	dev_t.t_wr_cycle = (t20 - t3) * 1000;
 
-	gpmc_calc_timings(&t, &dev_t);
+	gpmc_calc_timings(&t, &smc91x_settings, &dev_t);
 
 	return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
 }
@@ -133,6 +125,18 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
 	gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f;
 	gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
 
+	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
+		smc91x_settings.mux_add_data = GPMC_MUX_AD;
+	if (gpmc_cfg->flags & GPMC_READ_MON)
+		smc91x_settings.wait_on_read = true;
+	if (gpmc_cfg->flags & GPMC_WRITE_MON)
+		smc91x_settings.wait_on_write = true;
+	if (gpmc_cfg->wait_pin)
+		smc91x_settings.wait_pin = gpmc_cfg->wait_pin;
+	ret = gpmc_cs_program_settings(gpmc_cfg->cs, &smc91x_settings);
+	if (ret < 0)
+		goto free1;
+
 	if (gpmc_cfg->retime) {
 		ret = gpmc_cfg->retime();
 		if (ret != 0)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 8033cb7..993cb5e 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -25,6 +25,12 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_mtd.h>
+#include <linux/of_device.h>
+#include <linux/mtd/nand.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <linux/platform_data/mtd-nand-omap2.h>
 
@@ -34,6 +40,8 @@
 #include "common.h"
 #include "omap_device.h"
 #include "gpmc.h"
+#include "gpmc-nand.h"
+#include "gpmc-onenand.h"
 
 #define	DEVICE_NAME		"omap-gpmc"
 
@@ -85,9 +93,7 @@
 #define GPMC_CS_SIZE		0x30
 #define	GPMC_BCH_SIZE		0x10
 
-#define GPMC_MEM_START		0x00000000
 #define GPMC_MEM_END		0x3FFFFFFF
-#define BOOT_ROM_SPACE		0x100000	/* 1MB */
 
 #define GPMC_CHUNK_SHIFT	24		/* 16 MB */
 #define GPMC_SECTION_SHIFT	28		/* 128 MB */
@@ -101,6 +107,9 @@
 
 #define	GPMC_HAS_WR_ACCESS		0x1
 #define	GPMC_HAS_WR_DATA_MUX_BUS	0x2
+#define	GPMC_HAS_MUX_AAD		0x4
+
+#define GPMC_NR_WAITPINS		4
 
 /* XXX: Only NAND irq has been considered,currently these are the only ones used
  */
@@ -145,7 +154,9 @@ static unsigned gpmc_irq_start;
 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 */
+/* Define chip-selects as reserved by default until probe completes */
+static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1);
+static unsigned int gpmc_nr_waitpins;
 static struct device *gpmc_dev;
 static int gpmc_irq;
 static resource_size_t phys_base, mem_size;
@@ -174,7 +185,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val)
 	__raw_writel(val, reg_addr);
 }
 
-u32 gpmc_cs_read_reg(int cs, int idx)
+static u32 gpmc_cs_read_reg(int cs, int idx)
 {
 	void __iomem *reg_addr;
 
@@ -183,7 +194,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
 }
 
 /* TODO: Add support for gpmc_fck to clock framework and use it */
-unsigned long gpmc_get_fclk_period(void)
+static unsigned long gpmc_get_fclk_period(void)
 {
 	unsigned long rate = clk_get_rate(gpmc_l3_clk);
 
@@ -198,7 +209,7 @@ unsigned long gpmc_get_fclk_period(void)
 	return rate;
 }
 
-unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
+static unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
 {
 	unsigned long tick_ps;
 
@@ -208,7 +219,7 @@ unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
 	return (time_ns * 1000 + tick_ps - 1) / tick_ps;
 }
 
-unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
+static unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
 {
 	unsigned long tick_ps;
 
@@ -223,13 +234,6 @@ unsigned int gpmc_ticks_to_ns(unsigned int ticks)
 	return ticks * gpmc_get_fclk_period() / 1000;
 }
 
-unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
-{
-	unsigned long ticks = gpmc_ns_to_ticks(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();
@@ -398,11 +402,18 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 	return 0;
 }
 
-static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
+static int gpmc_cs_enable_mem(int cs, u32 base, u32 size)
 {
 	u32 l;
 	u32 mask;
 
+	/*
+	 * Ensure that base address is aligned on a
+	 * boundary equal to or greater than size.
+	 */
+	if (base & (size - 1))
+		return -EINVAL;
+
 	mask = (1 << GPMC_SECTION_SHIFT) - size;
 	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
 	l &= ~0x3f;
@@ -411,6 +422,8 @@ static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
 	l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8;
 	l |= GPMC_CONFIG7_CSVALID;
 	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+
+	return 0;
 }
 
 static void gpmc_cs_disable_mem(int cs)
@@ -441,22 +454,14 @@ static int gpmc_cs_mem_enabled(int cs)
 	return l & GPMC_CONFIG7_CSVALID;
 }
 
-int gpmc_cs_set_reserved(int cs, int reserved)
+static void gpmc_cs_set_reserved(int cs, int reserved)
 {
-	if (cs > GPMC_CS_NUM)
-		return -ENODEV;
-
 	gpmc_cs_map &= ~(1 << cs);
 	gpmc_cs_map |= (reserved ? 1 : 0) << cs;
-
-	return 0;
 }
 
-int gpmc_cs_reserved(int cs)
+static bool gpmc_cs_reserved(int cs)
 {
-	if (cs > GPMC_CS_NUM)
-		return -ENODEV;
-
 	return gpmc_cs_map & (1 << cs);
 }
 
@@ -503,6 +508,39 @@ static int gpmc_cs_delete_mem(int cs)
 	return r;
 }
 
+/**
+ * gpmc_cs_remap - remaps a chip-select physical base address
+ * @cs:		chip-select to remap
+ * @base:	physical base address to re-map chip-select to
+ *
+ * Re-maps a chip-select to a new physical base address specified by
+ * "base". Returns 0 on success and appropriate negative error code
+ * on failure.
+ */
+static int gpmc_cs_remap(int cs, u32 base)
+{
+	int ret;
+	u32 old_base, size;
+
+	if (cs > GPMC_CS_NUM)
+		return -ENODEV;
+	gpmc_cs_get_memconf(cs, &old_base, &size);
+	if (base == old_base)
+		return 0;
+	gpmc_cs_disable_mem(cs);
+	ret = gpmc_cs_delete_mem(cs);
+	if (ret < 0)
+		return ret;
+	ret = gpmc_cs_insert_mem(cs, base, size);
+	if (ret < 0)
+		return ret;
+	ret = gpmc_cs_enable_mem(cs, base, size);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 {
 	struct resource *res = &gpmc_cs_mem[cs];
@@ -528,7 +566,12 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	if (r < 0)
 		goto out;
 
-	gpmc_cs_enable_mem(cs, res->start, resource_size(res));
+	r = gpmc_cs_enable_mem(cs, res->start, resource_size(res));
+	if (r < 0) {
+		release_resource(res);
+		goto out;
+	}
+
 	*base = res->start;
 	gpmc_cs_set_reserved(cs, 1);
 out:
@@ -554,16 +597,14 @@ void gpmc_cs_free(int cs)
 EXPORT_SYMBOL(gpmc_cs_free);
 
 /**
- * gpmc_cs_configure - write request to configure gpmc
- * @cs: chip select number
+ * gpmc_configure - write request to configure gpmc
  * @cmd: command type
  * @wval: value to write
  * @return status of the operation
  */
-int gpmc_cs_configure(int cs, int cmd, int wval)
+int gpmc_configure(int cmd, int wval)
 {
-	int err = 0;
-	u32 regval = 0;
+	u32 regval;
 
 	switch (cmd) {
 	case GPMC_ENABLE_IRQ:
@@ -583,43 +624,14 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
 		gpmc_write_reg(GPMC_CONFIG, regval);
 		break;
 
-	case GPMC_CONFIG_RDY_BSY:
-		regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-		if (wval)
-			regval |= WR_RD_PIN_MONITORING;
-		else
-			regval &= ~WR_RD_PIN_MONITORING;
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
-		break;
-
-	case GPMC_CONFIG_DEV_SIZE:
-		regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
-		/* clear 2 target bits */
-		regval &= ~GPMC_CONFIG1_DEVICESIZE(3);
-
-		/* set the proper value */
-		regval |= GPMC_CONFIG1_DEVICESIZE(wval);
-
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
-		break;
-
-	case GPMC_CONFIG_DEV_TYPE:
-		regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-		regval |= GPMC_CONFIG1_DEVICETYPE(wval);
-		if (wval == GPMC_DEVICETYPE_NOR)
-			regval |= GPMC_CONFIG1_MUXADDDATA;
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
-		break;
-
 	default:
-		printk(KERN_ERR "gpmc_configure_cs: Not supported\n");
-		err = -EINVAL;
+		pr_err("%s: command not supported\n", __func__);
+		return -EINVAL;
 	}
 
-	return err;
+	return 0;
 }
-EXPORT_SYMBOL(gpmc_cs_configure);
+EXPORT_SYMBOL(gpmc_configure);
 
 void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
 {
@@ -774,19 +786,16 @@ static void gpmc_mem_exit(void)
 
 }
 
-static int gpmc_mem_init(void)
+static void gpmc_mem_init(void)
 {
-	int cs, rc;
-	unsigned long boot_rom_space = 0;
+	int cs;
 
-	/* never allocate the first page, to facilitate bug detection;
-	 * even if we didn't boot from ROM.
+	/*
+	 * The first 1MB of GPMC address space is typically mapped to
+	 * the internal ROM. Never allocate the first page, to
+	 * facilitate bug detection; even if we didn't boot from ROM.
 	 */
-	boot_rom_space = BOOT_ROM_SPACE;
-	/* In apollon the CS0 is mapped as 0x0000 0000 */
-	if (machine_is_omap_apollon())
-		boot_rom_space = 0;
-	gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
+	gpmc_mem_root.start = SZ_1M;
 	gpmc_mem_root.end = GPMC_MEM_END;
 
 	/* Reserve all regions that has been set up by bootloader */
@@ -796,16 +805,13 @@ static int gpmc_mem_init(void)
 		if (!gpmc_cs_mem_enabled(cs))
 			continue;
 		gpmc_cs_get_memconf(cs, &base, &size);
-		rc = gpmc_cs_insert_mem(cs, base, size);
-		if (IS_ERR_VALUE(rc)) {
-			while (--cs >= 0)
-				if (gpmc_cs_mem_enabled(cs))
-					gpmc_cs_delete_mem(cs);
-			return rc;
+
+		if (gpmc_cs_insert_mem(cs, base, size)) {
+			pr_warn("%s: disabling cs %d mapped at 0x%x-0x%x\n",
+				__func__, cs, base, base + size);
+			gpmc_cs_disable_mem(cs);
 		}
 	}
-
-	return 0;
 }
 
 static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
@@ -821,9 +827,9 @@ static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
 
 /* XXX: can the cycles be avoided ? */
 static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
-				struct gpmc_device_timings *dev_t)
+				       struct gpmc_device_timings *dev_t,
+				       bool mux)
 {
-	bool mux = dev_t->mux;
 	u32 temp;
 
 	/* adv_rd_off */
@@ -876,9 +882,9 @@ static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
 }
 
 static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
-				struct gpmc_device_timings *dev_t)
+					struct gpmc_device_timings *dev_t,
+					bool mux)
 {
-	bool mux = dev_t->mux;
 	u32 temp;
 
 	/* adv_wr_off */
@@ -938,9 +944,9 @@ static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
 }
 
 static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
-				struct gpmc_device_timings *dev_t)
+					struct gpmc_device_timings *dev_t,
+					bool mux)
 {
-	bool mux = dev_t->mux;
 	u32 temp;
 
 	/* adv_rd_off */
@@ -978,9 +984,9 @@ static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
 }
 
 static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t,
-				struct gpmc_device_timings *dev_t)
+					 struct gpmc_device_timings *dev_t,
+					 bool mux)
 {
-	bool mux = dev_t->mux;
 	u32 temp;
 
 	/* adv_wr_off */
@@ -1050,7 +1056,8 @@ static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t,
 }
 
 static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
-			struct gpmc_device_timings *dev_t)
+				    struct gpmc_device_timings *dev_t,
+				    bool sync)
 {
 	u32 temp;
 
@@ -1064,7 +1071,7 @@ static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
 				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)
+	if (sync)
 		gpmc_calc_sync_common_timings(gpmc_t, dev_t);
 
 	return 0;
@@ -1099,21 +1106,29 @@ static void gpmc_convert_ps_to_ns(struct gpmc_timings *t)
 }
 
 int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
-			struct gpmc_device_timings *dev_t)
+		      struct gpmc_settings *gpmc_s,
+		      struct gpmc_device_timings *dev_t)
 {
+	bool mux = false, sync = false;
+
+	if (gpmc_s) {
+		mux = gpmc_s->mux_add_data ? true : false;
+		sync = (gpmc_s->sync_read || gpmc_s->sync_write);
+	}
+
 	memset(gpmc_t, 0, sizeof(*gpmc_t));
 
-	gpmc_calc_common_timings(gpmc_t, dev_t);
+	gpmc_calc_common_timings(gpmc_t, dev_t, sync);
 
-	if (dev_t->sync_read)
-		gpmc_calc_sync_read_timings(gpmc_t, dev_t);
+	if (gpmc_s && gpmc_s->sync_read)
+		gpmc_calc_sync_read_timings(gpmc_t, dev_t, mux);
 	else
-		gpmc_calc_async_read_timings(gpmc_t, dev_t);
+		gpmc_calc_async_read_timings(gpmc_t, dev_t, mux);
 
-	if (dev_t->sync_write)
-		gpmc_calc_sync_write_timings(gpmc_t, dev_t);
+	if (gpmc_s && gpmc_s->sync_write)
+		gpmc_calc_sync_write_timings(gpmc_t, dev_t, mux);
 	else
-		gpmc_calc_async_write_timings(gpmc_t, dev_t);
+		gpmc_calc_async_write_timings(gpmc_t, dev_t, mux);
 
 	/* TODO: remove, see function definition */
 	gpmc_convert_ps_to_ns(gpmc_t);
@@ -1121,11 +1136,441 @@ int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
 	return 0;
 }
 
+/**
+ * gpmc_cs_program_settings - programs non-timing related settings
+ * @cs:		GPMC chip-select to program
+ * @p:		pointer to GPMC settings structure
+ *
+ * Programs non-timing related settings for a GPMC chip-select, such as
+ * bus-width, burst configuration, etc. Function should be called once
+ * for each chip-select that is being used and must be called before
+ * calling gpmc_cs_set_timings() as timing parameters in the CONFIG1
+ * register will be initialised to zero by this function. Returns 0 on
+ * success and appropriate negative error code on failure.
+ */
+int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
+{
+	u32 config1;
+
+	if ((!p->device_width) || (p->device_width > GPMC_DEVWIDTH_16BIT)) {
+		pr_err("%s: invalid width %d!", __func__, p->device_width);
+		return -EINVAL;
+	}
+
+	/* Address-data multiplexing not supported for NAND devices */
+	if (p->device_nand && p->mux_add_data) {
+		pr_err("%s: invalid configuration!\n", __func__);
+		return -EINVAL;
+	}
+
+	if ((p->mux_add_data > GPMC_MUX_AD) ||
+	    ((p->mux_add_data == GPMC_MUX_AAD) &&
+	     !(gpmc_capability & GPMC_HAS_MUX_AAD))) {
+		pr_err("%s: invalid multiplex configuration!\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Page/burst mode supports lengths of 4, 8 and 16 bytes */
+	if (p->burst_read || p->burst_write) {
+		switch (p->burst_len) {
+		case GPMC_BURST_4:
+		case GPMC_BURST_8:
+		case GPMC_BURST_16:
+			break;
+		default:
+			pr_err("%s: invalid page/burst-length (%d)\n",
+			       __func__, p->burst_len);
+			return -EINVAL;
+		}
+	}
+
+	if ((p->wait_on_read || p->wait_on_write) &&
+	    (p->wait_pin > gpmc_nr_waitpins)) {
+		pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
+		return -EINVAL;
+	}
+
+	config1 = GPMC_CONFIG1_DEVICESIZE((p->device_width - 1));
+
+	if (p->sync_read)
+		config1 |= GPMC_CONFIG1_READTYPE_SYNC;
+	if (p->sync_write)
+		config1 |= GPMC_CONFIG1_WRITETYPE_SYNC;
+	if (p->wait_on_read)
+		config1 |= GPMC_CONFIG1_WAIT_READ_MON;
+	if (p->wait_on_write)
+		config1 |= GPMC_CONFIG1_WAIT_WRITE_MON;
+	if (p->wait_on_read || p->wait_on_write)
+		config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin);
+	if (p->device_nand)
+		config1	|= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND);
+	if (p->mux_add_data)
+		config1	|= GPMC_CONFIG1_MUXTYPE(p->mux_add_data);
+	if (p->burst_read)
+		config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP;
+	if (p->burst_write)
+		config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP;
+	if (p->burst_read || p->burst_write) {
+		config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3);
+		config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0;
+	}
+	if (p->clk_activation)
+		config1 |= GPMC_CONFIG1_CLKACTIVATIONTIME(p->clk_activation);
+
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, config1);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id gpmc_dt_ids[] = {
+	{ .compatible = "ti,omap2420-gpmc" },
+	{ .compatible = "ti,omap2430-gpmc" },
+	{ .compatible = "ti,omap3430-gpmc" },	/* omap3430 & omap3630 */
+	{ .compatible = "ti,omap4430-gpmc" },	/* omap4430 & omap4460 & omap543x */
+	{ .compatible = "ti,am3352-gpmc" },	/* am335x devices */
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
+
+/**
+ * gpmc_read_settings_dt - read gpmc settings from device-tree
+ * @np:		pointer to device-tree node for a gpmc child device
+ * @p:		pointer to gpmc settings structure
+ *
+ * Reads the GPMC settings for a GPMC child device from device-tree and
+ * stores them in the GPMC settings structure passed. The GPMC settings
+ * structure is initialised to zero by this function and so any
+ * previously stored settings will be cleared.
+ */
+void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
+{
+	memset(p, 0, sizeof(struct gpmc_settings));
+
+	p->sync_read = of_property_read_bool(np, "gpmc,sync-read");
+	p->sync_write = of_property_read_bool(np, "gpmc,sync-write");
+	p->device_nand = of_property_read_bool(np, "gpmc,device-nand");
+	of_property_read_u32(np, "gpmc,device-width", &p->device_width);
+	of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data);
+	of_property_read_u32(np, "gpmc,clk-activation", &p->clk_activation);
+
+	if (!of_property_read_u32(np, "gpmc,burst-length", &p->burst_len)) {
+		p->burst_wrap = of_property_read_bool(np, "gpmc,burst-wrap");
+		p->burst_read = of_property_read_bool(np, "gpmc,burst-read");
+		p->burst_write = of_property_read_bool(np, "gpmc,burst-write");
+		if (!p->burst_read && !p->burst_write)
+			pr_warn("%s: page/burst-length set but not used!\n",
+				__func__);
+	}
+
+	if (!of_property_read_u32(np, "gpmc,wait-pin", &p->wait_pin)) {
+		p->wait_on_read = of_property_read_bool(np,
+							"gpmc,wait-on-read");
+		p->wait_on_write = of_property_read_bool(np,
+							 "gpmc,wait-on-write");
+		if (!p->wait_on_read && !p->wait_on_write)
+			pr_warn("%s: read/write wait monitoring not enabled!\n",
+				__func__);
+	}
+}
+
+static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
+						struct gpmc_timings *gpmc_t)
+{
+	struct gpmc_bool_timings *p;
+
+	if (!np || !gpmc_t)
+		return;
+
+	memset(gpmc_t, 0, sizeof(*gpmc_t));
+
+	/* minimum clock period for syncronous mode */
+	of_property_read_u32(np, "gpmc,sync-clk-ps", &gpmc_t->sync_clk);
+
+	/* chip select timtings */
+	of_property_read_u32(np, "gpmc,cs-on-ns", &gpmc_t->cs_on);
+	of_property_read_u32(np, "gpmc,cs-rd-off-ns", &gpmc_t->cs_rd_off);
+	of_property_read_u32(np, "gpmc,cs-wr-off-ns", &gpmc_t->cs_wr_off);
+
+	/* ADV signal timings */
+	of_property_read_u32(np, "gpmc,adv-on-ns", &gpmc_t->adv_on);
+	of_property_read_u32(np, "gpmc,adv-rd-off-ns", &gpmc_t->adv_rd_off);
+	of_property_read_u32(np, "gpmc,adv-wr-off-ns", &gpmc_t->adv_wr_off);
+
+	/* WE signal timings */
+	of_property_read_u32(np, "gpmc,we-on-ns", &gpmc_t->we_on);
+	of_property_read_u32(np, "gpmc,we-off-ns", &gpmc_t->we_off);
+
+	/* OE signal timings */
+	of_property_read_u32(np, "gpmc,oe-on-ns", &gpmc_t->oe_on);
+	of_property_read_u32(np, "gpmc,oe-off-ns", &gpmc_t->oe_off);
+
+	/* access and cycle timings */
+	of_property_read_u32(np, "gpmc,page-burst-access-ns",
+			     &gpmc_t->page_burst_access);
+	of_property_read_u32(np, "gpmc,access-ns", &gpmc_t->access);
+	of_property_read_u32(np, "gpmc,rd-cycle-ns", &gpmc_t->rd_cycle);
+	of_property_read_u32(np, "gpmc,wr-cycle-ns", &gpmc_t->wr_cycle);
+	of_property_read_u32(np, "gpmc,bus-turnaround-ns",
+			     &gpmc_t->bus_turnaround);
+	of_property_read_u32(np, "gpmc,cycle2cycle-delay-ns",
+			     &gpmc_t->cycle2cycle_delay);
+	of_property_read_u32(np, "gpmc,wait-monitoring-ns",
+			     &gpmc_t->wait_monitoring);
+	of_property_read_u32(np, "gpmc,clk-activation-ns",
+			     &gpmc_t->clk_activation);
+
+	/* only applicable to OMAP3+ */
+	of_property_read_u32(np, "gpmc,wr-access-ns", &gpmc_t->wr_access);
+	of_property_read_u32(np, "gpmc,wr-data-mux-bus-ns",
+			     &gpmc_t->wr_data_mux_bus);
+
+	/* bool timing parameters */
+	p = &gpmc_t->bool_timings;
+
+	p->cycle2cyclediffcsen =
+		of_property_read_bool(np, "gpmc,cycle2cycle-diffcsen");
+	p->cycle2cyclesamecsen =
+		of_property_read_bool(np, "gpmc,cycle2cycle-samecsen");
+	p->we_extra_delay = of_property_read_bool(np, "gpmc,we-extra-delay");
+	p->oe_extra_delay = of_property_read_bool(np, "gpmc,oe-extra-delay");
+	p->adv_extra_delay = of_property_read_bool(np, "gpmc,adv-extra-delay");
+	p->cs_extra_delay = of_property_read_bool(np, "gpmc,cs-extra-delay");
+	p->time_para_granularity =
+		of_property_read_bool(np, "gpmc,time-para-granularity");
+}
+
+#ifdef CONFIG_MTD_NAND
+
+static const char * const nand_ecc_opts[] = {
+	[OMAP_ECC_HAMMING_CODE_DEFAULT]		= "sw",
+	[OMAP_ECC_HAMMING_CODE_HW]		= "hw",
+	[OMAP_ECC_HAMMING_CODE_HW_ROMCODE]	= "hw-romcode",
+	[OMAP_ECC_BCH4_CODE_HW]			= "bch4",
+	[OMAP_ECC_BCH8_CODE_HW]			= "bch8",
+};
+
+static int gpmc_probe_nand_child(struct platform_device *pdev,
+				 struct device_node *child)
+{
+	u32 val;
+	const char *s;
+	struct gpmc_timings gpmc_t;
+	struct omap_nand_platform_data *gpmc_nand_data;
+
+	if (of_property_read_u32(child, "reg", &val) < 0) {
+		dev_err(&pdev->dev, "%s has no 'reg' property\n",
+			child->full_name);
+		return -ENODEV;
+	}
+
+	gpmc_nand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_nand_data),
+				      GFP_KERNEL);
+	if (!gpmc_nand_data)
+		return -ENOMEM;
+
+	gpmc_nand_data->cs = val;
+	gpmc_nand_data->of_node = child;
+
+	if (!of_property_read_string(child, "ti,nand-ecc-opt", &s))
+		for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++)
+			if (!strcasecmp(s, nand_ecc_opts[val])) {
+				gpmc_nand_data->ecc_opt = val;
+				break;
+			}
+
+	val = of_get_nand_bus_width(child);
+	if (val == 16)
+		gpmc_nand_data->devsize = NAND_BUSWIDTH_16;
+
+	gpmc_read_timings_dt(child, &gpmc_t);
+	gpmc_nand_init(gpmc_nand_data, &gpmc_t);
+
+	return 0;
+}
+#else
+static int gpmc_probe_nand_child(struct platform_device *pdev,
+				 struct device_node *child)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_MTD_ONENAND
+static int gpmc_probe_onenand_child(struct platform_device *pdev,
+				 struct device_node *child)
+{
+	u32 val;
+	struct omap_onenand_platform_data *gpmc_onenand_data;
+
+	if (of_property_read_u32(child, "reg", &val) < 0) {
+		dev_err(&pdev->dev, "%s has no 'reg' property\n",
+			child->full_name);
+		return -ENODEV;
+	}
+
+	gpmc_onenand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_onenand_data),
+					 GFP_KERNEL);
+	if (!gpmc_onenand_data)
+		return -ENOMEM;
+
+	gpmc_onenand_data->cs = val;
+	gpmc_onenand_data->of_node = child;
+	gpmc_onenand_data->dma_channel = -1;
+
+	if (!of_property_read_u32(child, "dma-channel", &val))
+		gpmc_onenand_data->dma_channel = val;
+
+	gpmc_onenand_init(gpmc_onenand_data);
+
+	return 0;
+}
+#else
+static int gpmc_probe_onenand_child(struct platform_device *pdev,
+				    struct device_node *child)
+{
+	return 0;
+}
+#endif
+
+/**
+ * gpmc_probe_generic_child - configures the gpmc for a child device
+ * @pdev:	pointer to gpmc platform device
+ * @child:	pointer to device-tree node for child device
+ *
+ * Allocates and configures a GPMC chip-select for a child device.
+ * Returns 0 on success and appropriate negative error code on failure.
+ */
+static int gpmc_probe_generic_child(struct platform_device *pdev,
+				struct device_node *child)
+{
+	struct gpmc_settings gpmc_s;
+	struct gpmc_timings gpmc_t;
+	struct resource res;
+	unsigned long base;
+	int ret, cs;
+
+	if (of_property_read_u32(child, "reg", &cs) < 0) {
+		dev_err(&pdev->dev, "%s has no 'reg' property\n",
+			child->full_name);
+		return -ENODEV;
+	}
+
+	if (of_address_to_resource(child, 0, &res) < 0) {
+		dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
+			child->full_name);
+		return -ENODEV;
+	}
+
+	ret = gpmc_cs_request(cs, resource_size(&res), &base);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
+		return ret;
+	}
+
+	if (!of_property_read_bool(child, "gpmc,no-remap")) {
+		/*
+		 * FIXME: gpmc_cs_request() will map the CS to an arbitary
+		 * location in the gpmc address space. When booting with
+		 * device-tree we want the NOR flash to be mapped to the
+		 * location specified in the device-tree blob. So remap the
+		 * CS to this location. Once DT migration is complete should
+		 * just make gpmc_cs_request() map a specific address.
+		 */
+		ret = gpmc_cs_remap(cs, res.start);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n",
+				cs, res.start);
+			goto err;
+		}
+
+		dev_info(&pdev->dev, "GPMC%d: res.start=0x%x\n", cs, (unsigned int)res.start);
+	}
+
+	gpmc_read_settings_dt(child, &gpmc_s);
+
+	ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s has no 'bank-width' property\n",
+			child->full_name);
+		goto err;
+	}
+
+	ret = gpmc_cs_program_settings(cs, &gpmc_s);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s failed to program settings\n",
+			child->full_name);
+		goto err;
+	}
+
+	gpmc_read_timings_dt(child, &gpmc_t);
+	gpmc_cs_set_timings(cs, &gpmc_t);
+
+	if (of_platform_device_create(child, NULL, &pdev->dev))
+		return 0;
+
+	dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
+	ret = -ENODEV;
+
+err:
+	gpmc_cs_free(cs);
+
+	return ret;
+}
+
+static int gpmc_probe_dt(struct platform_device *pdev)
+{
+	int ret;
+	struct device_node *node = pdev->dev.of_node;
+	struct device_node *child;
+
+	ret = of_property_read_u32(node, "gpmc,num-waitpins",
+				   &gpmc_nr_waitpins);
+	if (ret < 0) {
+		pr_err("%s: number of wait pins not found!\n", __func__);
+		return ret;
+	}
+
+	for_each_available_child_of_node(node, child) {
+
+		if (!child->name)
+			continue;
+
+		ret = 0;
+		if (of_node_cmp(child->name, "nand") == 0)
+			ret = gpmc_probe_nand_child(pdev, child);
+		else if (of_node_cmp(child->name, "onenand") == 0)
+			ret = gpmc_probe_onenand_child(pdev, child);
+		else if (of_node_cmp(child->name, "nor") == 0 ||
+			   of_node_cmp(child->name, "ethernet") == 0 ||
+			   of_node_cmp(child->name, "camera") == 0)
+			ret = gpmc_probe_generic_child(pdev, child);
+
+		if (ret < 0) {
+			of_node_put(child);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+#else
+static int gpmc_probe_dt(struct platform_device *pdev)
+{
+	return 0;
+}
+#endif
+
 static int gpmc_probe(struct platform_device *pdev)
 {
 	int rc;
 	u32 l;
 	struct resource *res;
+	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");
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res == NULL)
@@ -1158,21 +1603,45 @@ static int gpmc_probe(struct platform_device *pdev)
 	gpmc_dev = &pdev->dev;
 
 	l = gpmc_read_reg(GPMC_REVISION);
+
+	/*
+	 * FIXME: Once device-tree migration is complete the below flags
+	 * should be populated based upon the device-tree compatible
+	 * string. For now just use the IP revision. OMAP3+ devices have
+	 * the wr_access and wr_data_mux_bus register fields. OMAP4+
+	 * devices support the addr-addr-data multiplex protocol.
+	 *
+	 * GPMC IP revisions:
+	 * - OMAP24xx			= 2.0
+	 * - OMAP3xxx			= 5.0
+	 * - OMAP44xx/54xx/AM335x	= 6.0
+	 */
 	if (GPMC_REVISION_MAJOR(l) > 0x4)
 		gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS;
+	if (GPMC_REVISION_MAJOR(l) > 0x5)
+		gpmc_capability |= GPMC_HAS_MUX_AAD;
 	dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
 		 GPMC_REVISION_MINOR(l));
 
-	rc = gpmc_mem_init();
-	if (IS_ERR_VALUE(rc)) {
+	gpmc_mem_init();
+
+	if (IS_ERR_VALUE(gpmc_setup_irq()))
+		dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
+
+	/* Now the GPMC is initialised, unreserve the chip-selects */
+	gpmc_cs_map = 0;
+
+	if (!pdev->dev.of_node)
+		gpmc_nr_waitpins = GPMC_NR_WAITPINS;
+
+	rc = gpmc_probe_dt(pdev);
+	if (rc < 0) {
 		clk_disable_unprepare(gpmc_l3_clk);
 		clk_put(gpmc_l3_clk);
-		dev_err(gpmc_dev, "failed to reserve memory\n");
+		dev_err(gpmc_dev, "failed to probe DT parameters\n");
 		return rc;
 	}
-
-	if (IS_ERR_VALUE(gpmc_setup_irq()))
-		dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
+	dev_info(gpmc_dev, "loaded OK\n");
 
 	return 0;
 }
@@ -1191,6 +1660,7 @@ static struct platform_driver gpmc_driver = {
 	.driver		= {
 		.name	= DEVICE_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table	= of_match_ptr(gpmc_dt_ids),
 	},
 };
 
@@ -1214,6 +1684,13 @@ static int __init omap_gpmc_init(void)
 	struct platform_device *pdev;
 	char *oh_name = "gpmc";
 
+	/*
+	 * if the board boots up with a populated DT, do not
+	 * manually add the device from this initcall
+	 */
+	if (of_have_populated_dt())
+		return -ENODEV;
+
 	oh = omap_hwmod_lookup(oh_name);
 	if (!oh) {
 		pr_err("Could not look up %s\n", oh_name);
diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
index fe0a844..b329bb8 100644
--- a/arch/arm/mach-omap2/gpmc.h
+++ b/arch/arm/mach-omap2/gpmc.h
@@ -58,7 +58,7 @@
 #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_MUXTYPE(val)       ((val & 3) << 8)
 #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))
@@ -73,6 +73,13 @@
 #define GPMC_IRQ_FIFOEVENTENABLE	0x01
 #define GPMC_IRQ_COUNT_EVENT		0x02
 
+#define GPMC_BURST_4			4	/* 4 word burst */
+#define GPMC_BURST_8			8	/* 8 word burst */
+#define GPMC_BURST_16			16	/* 16 word burst */
+#define GPMC_DEVWIDTH_8BIT		1	/* 8-bit device width */
+#define GPMC_DEVWIDTH_16BIT		2	/* 16-bit device width */
+#define GPMC_MUX_AAD			1	/* Addr-Addr-Data multiplex */
+#define GPMC_MUX_AD			2	/* Addr-Data multiplex */
 
 /* bool type time settings */
 struct gpmc_bool_timings {
@@ -178,10 +185,6 @@ struct gpmc_device_timings {
 	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;
@@ -189,28 +192,41 @@ struct gpmc_device_timings {
 	bool we_xdelay;
 };
 
+struct gpmc_settings {
+	bool burst_wrap;	/* enables wrap bursting */
+	bool burst_read;	/* enables read page/burst mode */
+	bool burst_write;	/* enables write page/burst mode */
+	bool device_nand;	/* device is NAND */
+	bool sync_read;		/* enables synchronous reads */
+	bool sync_write;	/* enables synchronous writes */
+	bool wait_on_read;	/* monitor wait on reads */
+	bool wait_on_write;	/* monitor wait on writes */
+	u32 burst_len;		/* page/burst length */
+	u32 device_width;	/* device bus width (8 or 16 bit) */
+	u32 mux_add_data;	/* multiplex address & data */
+	u32 wait_pin;		/* wait-pin to be used */
+	u32 clk_activation;	/* clock activation time */
+};
+
 extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
-				struct gpmc_device_timings *dev_t);
+			     struct gpmc_settings *gpmc_s,
+			     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_program_settings(int cs, struct gpmc_settings *p);
 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);
+extern int gpmc_configure(int cmd, int wval);
+extern void gpmc_read_settings_dt(struct device_node *np,
+				  struct gpmc_settings *p);
 
 #endif
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 3926f37..57d1b7d 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -233,7 +233,7 @@ static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs
 			goto out;
 
 		irqnr = readl_relaxed(base_addr + 0xd8);
-#ifdef CONFIG_SOC_TI81XX
+#if defined(CONFIG_SOC_TI81XX) || defined(CONFIG_SOC_AM33XX)
 		if (irqnr)
 			goto out;
 		irqnr = readl_relaxed(base_addr + 0xf8);
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index e065daa..2cf12c1 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -329,8 +329,8 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
 	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;
+	const char *oh_name, *rst_name;
+	int oh_cnt, dstr_cnt, i, ret = 0;
 
 	oh_cnt = of_property_count_strings(node, "ti,hwmods");
 	if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
@@ -375,6 +375,27 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
 	if (of_get_property(node, "ti,no_idle_on_suspend", NULL))
 		omap_device_disable_idle_on_suspend(pdev);
 
+	dstr_cnt =
+		of_property_count_strings(node, "ti,deassert-hard-reset");
+	if (dstr_cnt > 0) {
+		for (i = 0; i < dstr_cnt; i += 2) {
+			of_property_read_string_index(
+				node, "ti,deassert-hard-reset", i,
+				&oh_name);
+			of_property_read_string_index(
+				node, "ti,deassert-hard-reset", i+1,
+				&rst_name);
+			oh = omap_hwmod_lookup(oh_name);
+			if (!oh) {
+				dev_warn(&pdev->dev,
+				"Cannot parse deassert property for '%s'\n",
+				oh_name);
+				break;
+			}
+			omap_hwmod_deassert_hardreset(oh, rst_name);
+		}
+	}
+
 	pdev->dev.pm_domain = &omap_device_pm_domain;
 
 odbfd_exit1:
@@ -494,30 +515,156 @@ static int omap_device_fill_resources(struct omap_device *od,
 }
 
 /**
- * _od_fill_dma_resources - fill in array of struct resource with dma resources
+ * omap_device_fixup_resources - Fix platform device 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.
+ * Fixup the platform device resources so that the resources
+ * from the hwmods are included for.
  */
-static int _od_fill_dma_resources(struct omap_device *od,
-				      struct resource *res)
+static int omap_device_fixup_resources(struct omap_device *od)
 {
-	int i, r;
+	struct platform_device *pdev = od->pdev;
+	int i, j, ret, res_count;
+	struct resource *res, *r, *rnew, *rn;
+	unsigned long type;
 
-	for (i = 0; i < od->hwmods_cnt; i++) {
-		r = omap_hwmod_fill_dma_resources(od->hwmods[i], res);
-		res += r;
+	/*
+	 * 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.
+	 */
+
+	/* count number of resources hwmod provides */
+	res_count = omap_device_count_resources(od, IORESOURCE_IRQ |
+					IORESOURCE_DMA | IORESOURCE_MEM);
+
+	/* if no resources from hwmod, we're done already */
+	if (res_count == 0)
+		return 0;
+
+	/* Allocate resources memory to account for all hwmod resources */
+	res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
+	if (!res) {
+		ret = -ENOMEM;
+		goto fail_no_res;
 	}
 
+	/* fill all the resources */
+	ret = omap_device_fill_resources(od, res);
+	if (ret != 0)
+		goto fail_no_fill;
+
+	/*
+	 * 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 > 0) {
+
+		dev_dbg(&pdev->dev, "%s(): resources allocated %d hwmod #%d\n",
+			__func__, pdev->num_resources, res_count);
+
+		/* find number of resources needing to be inserted */
+		for (i = 0, j = 0, r = res; i < res_count; i++, r++) {
+			type = resource_type(r);
+			if (type == IORESOURCE_DMA)
+				j++;
+		}
+
+		/* no need to insert anything, just return */
+		if (j == 0) {
+			kfree(res);
+			return 0;
+		}
+
+		/* we need to insert j additional resources */
+		rnew = kzalloc(sizeof(*rnew) *
+				(pdev->num_resources + j), GFP_KERNEL);
+		if (rnew == NULL)
+			goto fail_no_rnew;
+
+		/*
+		 * Unlink any resources from any lists.
+		 * This is important since the copying destroys any
+		 * linkage
+		 */
+		for (i = 0, r = pdev->resource;
+				i < pdev->num_resources; i++, r++) {
+
+			if (!r->parent)
+				continue;
+
+			dev_dbg(&pdev->dev,
+					"Releasing resource %p\n", r);
+			release_resource(r);
+			r->parent = NULL;
+			r->sibling = NULL;
+			r->child = NULL;
+		}
+
+		memcpy(rnew, pdev->resource,
+				sizeof(*rnew) * pdev->num_resources);
+
+		/* now append the resources from the hwmods */
+		rn = rnew + pdev->num_resources;
+		for (i = 0, r = res; i < res_count; i++, r++) {
+
+			type = resource_type(r);
+			if (type != IORESOURCE_DMA)
+				continue;
+
+			/* append the hwmod resource */
+			memcpy(rn, r, sizeof(*r));
+
+			/* make sure these are zeroed out */
+			rn->parent = NULL;
+			rn->child = NULL;
+			rn->sibling = NULL;
+
+			rn++;
+		}
+		kfree(res);	/* we don't need res anymore */
+
+		/* this is our new resource table */
+		res = rnew;
+		res_count = j + pdev->num_resources;
+
+	} else {
+		dev_dbg(&pdev->dev, "%s(): using resources from hwmod %d\n",
+			__func__, res_count);
+	}
+
+	ret = platform_device_add_resources(pdev, res, res_count);
+	kfree(res);
+
+	/* failed to add the resources? */
+	if (ret != 0)
+		return ret;
+
+	/* finally link all the resources again */
+	ret = platform_device_link_resources(pdev);
+	if (ret != 0)
+		return ret;
+
 	return 0;
+
+fail_no_rnew:
+	/* nothing */
+fail_no_fill:
+	kfree(res);
+
+fail_no_res:
+	return ret;
 }
 
 /**
@@ -541,9 +688,8 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev,
 {
 	int ret = -ENOMEM;
 	struct omap_device *od;
-	struct resource *res = NULL;
-	int i, res_count;
 	struct omap_hwmod **hwmods;
+	int i;
 
 	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
 	if (!od) {
@@ -553,79 +699,18 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev,
 	od->hwmods_cnt = oh_cnt;
 
 	hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
-	if (!hwmods)
+	if (!hwmods) {
+		ret = -ENOMEM;
 		goto oda_exit2;
+	}
 
 	od->hwmods = hwmods;
 	od->pdev = pdev;
 
-	/*
-	 * Non-DT Boot:
-	 *   Here, pdev->num_resources = 0, and we should get all the
-	 *   resources from hwmod.
-	 *
-	 * 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).
-	 *   As preparation for the future we examine the OF provided resources
-	 *   to see if we have DMA resources provided already. In this case
-	 *   there is no need to update the resources for the device, we use the
-	 *   OF provided ones.
-	 *
-	 * TODO: Once DMA resource is available from OF layer, we should
-	 *   kill filling any resources from hwmod.
-	 */
-	if (!pdev->num_resources) {
-		/* Count all resources for the device */
-		res_count = omap_device_count_resources(od, IORESOURCE_IRQ |
-							    IORESOURCE_DMA |
-							    IORESOURCE_MEM);
-	} else {
-		/* Take a look if we already have DMA resource via DT */
-		for (i = 0; i < pdev->num_resources; i++) {
-			struct resource *r = &pdev->resource[i];
-
-			/* We have it, no need to touch the resources */
-			if (r->flags == IORESOURCE_DMA)
-				goto have_everything;
-		}
-		/* Count only DMA resources for the device */
-		res_count = omap_device_count_resources(od, IORESOURCE_DMA);
-		/* The device has no DMA resource, no need for update */
-		if (!res_count)
-			goto have_everything;
-
-		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) {
-		dev_dbg(&pdev->dev, "%s: using %d resources from hwmod\n",
-			__func__, res_count);
-		omap_device_fill_resources(od, res);
-	} else {
-		dev_dbg(&pdev->dev,
-			"%s: appending %d DMA resources from hwmod\n",
-			__func__, res_count - pdev->num_resources);
-		memcpy(res, pdev->resource,
-		       sizeof(struct resource) * pdev->num_resources);
-		_od_fill_dma_resources(od, &res[pdev->num_resources]);
-	}
-
-	ret = platform_device_add_resources(pdev, res, res_count);
-	kfree(res);
-
-	if (ret)
+	ret = omap_device_fixup_resources(od);
+	if (ret != 0)
 		goto oda_exit3;
 
-have_everything:
 	if (!pm_lats) {
 		pm_lats = omap_default_latency;
 		pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 4653efb..2b58e21 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -783,7 +783,9 @@ static int _init_interface_clks(struct omap_hwmod *oh)
 		if (IS_ERR(c)) {
 			pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n",
 				   oh->name, os->clk);
-			ret = -EINVAL;
+			if (ret == 0)
+				ret = -EINVAL;
+			continue;
 		}
 		os->_clk = c;
 		/*
@@ -819,7 +821,9 @@ static int _init_opt_clks(struct omap_hwmod *oh)
 		if (IS_ERR(c)) {
 			pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n",
 				   oh->name, oc->clk);
-			ret = -EINVAL;
+			if (ret == 0)
+				ret = -EINVAL;
+			continue;
 		}
 		oc->_clk = c;
 		/*
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index b5efe58..2a73d4b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -605,6 +605,8 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
 	&omap2420_l4_core__mcbsp2,
 	&omap2420_l4_core__msdi1,
 	&omap2xxx_l4_core__rng,
+	&omap2xxx_l4_core__sham,
+	&omap2xxx_l4_core__aes,
 	&omap2420_l4_core__hdq1w,
 	&omap2420_l4_wkup__counter_32k,
 	&omap2420_l3__gpmc,
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index d2d3840..4ce999e 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -963,6 +963,8 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
 	&omap2430_l4_core__mcbsp5,
 	&omap2430_l4_core__hdq1w,
 	&omap2xxx_l4_core__rng,
+	&omap2xxx_l4_core__sham,
+	&omap2xxx_l4_core__aes,
 	&omap2430_l4_wkup__counter_32k,
 	&omap2430_l3__gpmc,
 	NULL,
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 47901a5..8d4d53d 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
@@ -138,6 +138,24 @@ static struct omap_hwmod_addr_space omap2_rng_addr_space[] = {
 	{ }
 };
 
+struct omap_hwmod_addr_space omap2xxx_sham_addrs[] = {
+	{
+		.pa_start	= 0x480a4000,
+		.pa_end		= 0x480a4000 + 0x64 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_addr_space omap2xxx_aes_addrs[] = {
+	{
+		.pa_start	= 0x480a6000,
+		.pa_end		= 0x480a6000 + 0x50 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
 /*
  * Common interconnect data
  */
@@ -389,3 +407,21 @@ struct omap_hwmod_ocp_if omap2xxx_l4_core__rng = {
 	.addr		= omap2_rng_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
+
+/* l4 core -> sham interface */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__sham = {
+	.master		= &omap2xxx_l4_core_hwmod,
+	.slave		= &omap2xxx_sham_hwmod,
+	.clk		= "sha_ick",
+	.addr		= omap2xxx_sham_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> aes interface */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__aes = {
+	.master		= &omap2xxx_l4_core_hwmod,
+	.slave		= &omap2xxx_aes_hwmod,
+	.clk		= "aes_ick",
+	.addr		= omap2xxx_aes_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
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 e596117..da5b790 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -864,3 +864,84 @@ struct omap_hwmod omap2xxx_rng_hwmod = {
 	.flags		= HWMOD_INIT_NO_RESET,
 	.class		= &omap2_rng_hwmod_class,
 };
+
+/* SHAM */
+
+static struct omap_hwmod_class_sysconfig omap2_sham_sysc = {
+	.rev_offs	= 0x5c,
+	.sysc_offs	= 0x60,
+	.syss_offs	= 0x64,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2xxx_sham_class = {
+	.name	= "sham",
+	.sysc	= &omap2_sham_sysc,
+};
+
+struct omap_hwmod_irq_info omap2_sham_mpu_irqs[] = {
+	{ .irq = 51 + OMAP_INTC_START, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_dma_info omap2_sham_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 13 },
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod omap2xxx_sham_hwmod = {
+	.name		= "sham",
+	.mpu_irqs	= omap2_sham_mpu_irqs,
+	.sdma_reqs	= omap2_sham_sdma_chs,
+	.main_clk	= "l4_ck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 4,
+			.module_bit = OMAP24XX_EN_SHA_SHIFT,
+			.idlest_reg_id = 4,
+			.idlest_idle_bit = OMAP24XX_ST_SHA_SHIFT,
+		},
+	},
+	.class		= &omap2xxx_sham_class,
+};
+
+/* AES */
+
+static struct omap_hwmod_class_sysconfig omap2_aes_sysc = {
+	.rev_offs	= 0x44,
+	.sysc_offs	= 0x48,
+	.syss_offs	= 0x4c,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2xxx_aes_class = {
+	.name	= "aes",
+	.sysc	= &omap2_aes_sysc,
+};
+
+struct omap_hwmod_dma_info omap2_aes_sdma_chs[] = {
+	{ .name = "tx", .dma_req = 9 },
+	{ .name = "rx", .dma_req = 10 },
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod omap2xxx_aes_hwmod = {
+	.name		= "aes",
+	.sdma_reqs	= omap2_aes_sdma_chs,
+	.main_clk	= "l4_ck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 4,
+			.module_bit = OMAP24XX_EN_AES_SHIFT,
+			.idlest_reg_id = 4,
+			.idlest_idle_bit = OMAP24XX_ST_AES_SHIFT,
+		},
+	},
+	.class		= &omap2xxx_aes_class,
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
index 646c14d..6e80edb 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
@@ -416,8 +416,6 @@ static struct omap_hwmod am33xx_adc_tsc_hwmod = {
  *    - debugss
  *    - ocmc ram
  *    - ocp watch point
- *    - aes0
- *    - sha0
  */
 #if 0
 /*
@@ -517,25 +515,41 @@ static struct omap_hwmod am33xx_ocpwp_hwmod = {
 		},
 	},
 };
+#endif
 
 /*
- * 'aes' class
+ * 'aes0' class
  */
-static struct omap_hwmod_class am33xx_aes_hwmod_class = {
-	.name		= "aes",
+static struct omap_hwmod_class_sysconfig am33xx_aes0_sysc = {
+	.rev_offs	= 0x80,
+	.sysc_offs	= 0x84,
+	.syss_offs	= 0x88,
+	.sysc_flags	= SYSS_HAS_RESET_STATUS,
+};
+
+static struct omap_hwmod_class am33xx_aes0_hwmod_class = {
+	.name		= "aes0",
+	.sysc		= &am33xx_aes0_sysc,
 };
 
 static struct omap_hwmod_irq_info am33xx_aes0_irqs[] = {
-	{ .irq = 102 + OMAP_INTC_START, },
+	{ .irq = 103 + OMAP_INTC_START, },
 	{ .irq = -1 },
 };
 
+struct omap_hwmod_dma_info am33xx_aes0_edma_reqs[] = {
+	{ .name = "tx", .dma_req = 6, },
+	{ .name = "rx", .dma_req = 5, },
+	{ .dma_req = -1 }
+};
+
 static struct omap_hwmod am33xx_aes0_hwmod = {
-	.name		= "aes0",
-	.class		= &am33xx_aes_hwmod_class,
+	.name		= "aes",
+	.class		= &am33xx_aes0_hwmod_class,
 	.clkdm_name	= "l3_clkdm",
 	.mpu_irqs	= am33xx_aes0_irqs,
-	.main_clk	= "l3_gclk",
+	.sdma_reqs	= am33xx_aes0_edma_reqs,
+	.main_clk	= "aes0_fck",
 	.prcm		= {
 		.omap4	= {
 			.clkctrl_offs	= AM33XX_CM_PER_AES0_CLKCTRL_OFFSET,
@@ -544,21 +558,35 @@ static struct omap_hwmod am33xx_aes0_hwmod = {
 	},
 };
 
-/* sha0 */
+/* sha0 HIB2 (the 'P' (public) device) */
+static struct omap_hwmod_class_sysconfig am33xx_sha0_sysc = {
+	.rev_offs	= 0x100,
+	.sysc_offs	= 0x110,
+	.syss_offs	= 0x114,
+	.sysc_flags	= SYSS_HAS_RESET_STATUS,
+};
+
 static struct omap_hwmod_class am33xx_sha0_hwmod_class = {
 	.name		= "sha0",
+	.sysc		= &am33xx_sha0_sysc,
 };
 
 static struct omap_hwmod_irq_info am33xx_sha0_irqs[] = {
-	{ .irq = 108 + OMAP_INTC_START, },
+	{ .irq = 109 + OMAP_INTC_START, },
 	{ .irq = -1 },
 };
 
+struct omap_hwmod_dma_info am33xx_sha0_edma_reqs[] = {
+	{ .name = "rx", .dma_req = 36, },
+	{ .dma_req = -1 }
+};
+
 static struct omap_hwmod am33xx_sha0_hwmod = {
-	.name		= "sha0",
+	.name		= "sham",
 	.class		= &am33xx_sha0_hwmod_class,
 	.clkdm_name	= "l3_clkdm",
 	.mpu_irqs	= am33xx_sha0_irqs,
+	.sdma_reqs	= am33xx_sha0_edma_reqs,
 	.main_clk	= "l3_gclk",
 	.prcm		= {
 		.omap4	= {
@@ -568,8 +596,6 @@ static struct omap_hwmod am33xx_sha0_hwmod = {
 	},
 };
 
-#endif
-
 /* 'smartreflex' class */
 static struct omap_hwmod_class am33xx_smartreflex_hwmod_class = {
 	.name		= "smartreflex",
@@ -783,9 +809,7 @@ static struct omap_hwmod am33xx_elm_hwmod = {
 	},
 };
 
-/*
- * 'epwmss' class: ecap0,1,2,  ehrpwm0,1,2
- */
+/* pwmss  */
 static struct omap_hwmod_class_sysconfig am33xx_epwmss_sysc = {
 	.rev_offs	= 0x0,
 	.sysc_offs	= 0x4,
@@ -801,18 +825,23 @@ static struct omap_hwmod_class am33xx_epwmss_hwmod_class = {
 	.sysc		= &am33xx_epwmss_sysc,
 };
 
-/* ehrpwm0 */
-static struct omap_hwmod_irq_info am33xx_ehrpwm0_irqs[] = {
-	{ .name = "int", .irq = 86 + OMAP_INTC_START, },
-	{ .name = "tzint", .irq = 58 + OMAP_INTC_START, },
-	{ .irq = -1 },
+static struct omap_hwmod_class am33xx_ecap_hwmod_class = {
+	.name		= "ecap",
 };
 
-static struct omap_hwmod am33xx_ehrpwm0_hwmod = {
-	.name		= "ehrpwm0",
+static struct omap_hwmod_class am33xx_eqep_hwmod_class = {
+	.name		= "eqep",
+};
+
+static struct omap_hwmod_class am33xx_ehrpwm_hwmod_class = {
+	.name		= "ehrpwm",
+};
+
+/* epwmss0 */
+static struct omap_hwmod am33xx_epwmss0_hwmod = {
+	.name		= "epwmss0",
 	.class		= &am33xx_epwmss_hwmod_class,
 	.clkdm_name	= "l4ls_clkdm",
-	.mpu_irqs	= am33xx_ehrpwm0_irqs,
 	.main_clk	= "l4ls_gclk",
 	.prcm		= {
 		.omap4	= {
@@ -822,63 +851,58 @@ static struct omap_hwmod am33xx_ehrpwm0_hwmod = {
 	},
 };
 
-/* ehrpwm1 */
-static struct omap_hwmod_irq_info am33xx_ehrpwm1_irqs[] = {
-	{ .name = "int", .irq = 87 + OMAP_INTC_START, },
-	{ .name = "tzint", .irq = 59 + OMAP_INTC_START, },
+/* ecap0 */
+static struct omap_hwmod_irq_info am33xx_ecap0_irqs[] = {
+	{ .irq = 31 + OMAP_INTC_START, },
 	{ .irq = -1 },
 };
 
-static struct omap_hwmod am33xx_ehrpwm1_hwmod = {
-	.name		= "ehrpwm1",
-	.class		= &am33xx_epwmss_hwmod_class,
+static struct omap_hwmod am33xx_ecap0_hwmod = {
+	.name		= "ecap0",
+	.class		= &am33xx_ecap_hwmod_class,
 	.clkdm_name	= "l4ls_clkdm",
-	.mpu_irqs	= am33xx_ehrpwm1_irqs,
+	.mpu_irqs	= am33xx_ecap0_irqs,
 	.main_clk	= "l4ls_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
 };
 
-/* ehrpwm2 */
-static struct omap_hwmod_irq_info am33xx_ehrpwm2_irqs[] = {
-	{ .name = "int", .irq = 39 + OMAP_INTC_START, },
-	{ .name = "tzint", .irq = 60 + OMAP_INTC_START, },
+/* eqep0 */
+static struct omap_hwmod_irq_info am33xx_eqep0_irqs[] = {
+	{ .irq = 79 + OMAP_INTC_START, },
 	{ .irq = -1 },
 };
 
-static struct omap_hwmod am33xx_ehrpwm2_hwmod = {
-	.name		= "ehrpwm2",
-	.class		= &am33xx_epwmss_hwmod_class,
+static struct omap_hwmod am33xx_eqep0_hwmod = {
+	.name		= "eqep0",
+	.class		= &am33xx_eqep_hwmod_class,
 	.clkdm_name	= "l4ls_clkdm",
-	.mpu_irqs	= am33xx_ehrpwm2_irqs,
+	.mpu_irqs	= am33xx_eqep0_irqs,
 	.main_clk	= "l4ls_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
 };
 
-/* ecap0 */
-static struct omap_hwmod_irq_info am33xx_ecap0_irqs[] = {
-	{ .irq = 31 + OMAP_INTC_START, },
+/* ehrpwm0 */
+static struct omap_hwmod_irq_info am33xx_ehrpwm0_irqs[] = {
+	{ .name = "int", .irq = 86 + OMAP_INTC_START, },
+	{ .name = "tzint", .irq = 58 + OMAP_INTC_START, },
 	{ .irq = -1 },
 };
 
-static struct omap_hwmod am33xx_ecap0_hwmod = {
-	.name		= "ecap0",
+static struct omap_hwmod am33xx_ehrpwm0_hwmod = {
+	.name		= "ehrpwm0",
+	.class		= &am33xx_ehrpwm_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_ehrpwm0_irqs,
+	.main_clk	= "l4ls_gclk",
+};
+
+/* epwmss1 */
+static struct omap_hwmod am33xx_epwmss1_hwmod = {
+	.name		= "epwmss1",
 	.class		= &am33xx_epwmss_hwmod_class,
 	.clkdm_name	= "l4ls_clkdm",
-	.mpu_irqs	= am33xx_ecap0_irqs,
 	.main_clk	= "l4ls_gclk",
 	.prcm		= {
 		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET,
+			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET,
 			.modulemode	= MODULEMODE_SWCTRL,
 		},
 	},
@@ -892,13 +916,50 @@ static struct omap_hwmod_irq_info am33xx_ecap1_irqs[] = {
 
 static struct omap_hwmod am33xx_ecap1_hwmod = {
 	.name		= "ecap1",
-	.class		= &am33xx_epwmss_hwmod_class,
+	.class		= &am33xx_ecap_hwmod_class,
 	.clkdm_name	= "l4ls_clkdm",
 	.mpu_irqs	= am33xx_ecap1_irqs,
 	.main_clk	= "l4ls_gclk",
+};
+
+/* eqep1 */
+static struct omap_hwmod_irq_info am33xx_eqep1_irqs[] = {
+	{ .irq = 88 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_eqep1_hwmod = {
+	.name		= "eqep1",
+	.class		= &am33xx_eqep_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_eqep1_irqs,
+	.main_clk	= "l4ls_gclk",
+};
+
+/* ehrpwm1 */
+static struct omap_hwmod_irq_info am33xx_ehrpwm1_irqs[] = {
+	{ .name = "int", .irq = 87 + OMAP_INTC_START, },
+	{ .name = "tzint", .irq = 59 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_ehrpwm1_hwmod = {
+	.name		= "ehrpwm1",
+	.class		= &am33xx_ehrpwm_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_ehrpwm1_irqs,
+	.main_clk	= "l4ls_gclk",
+};
+
+/* epwmss2 */
+static struct omap_hwmod am33xx_epwmss2_hwmod = {
+	.name		= "epwmss2",
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
 	.prcm		= {
 		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET,
+			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET,
 			.modulemode	= MODULEMODE_SWCTRL,
 		},
 	},
@@ -912,16 +973,39 @@ static struct omap_hwmod_irq_info am33xx_ecap2_irqs[] = {
 
 static struct omap_hwmod am33xx_ecap2_hwmod = {
 	.name		= "ecap2",
+	.class		= &am33xx_ecap_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
 	.mpu_irqs	= am33xx_ecap2_irqs,
-	.class		= &am33xx_epwmss_hwmod_class,
+	.main_clk	= "l4ls_gclk",
+};
+
+/* eqep2 */
+static struct omap_hwmod_irq_info am33xx_eqep2_irqs[] = {
+	{ .irq = 89 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_eqep2_hwmod = {
+	.name		= "eqep2",
+	.class		= &am33xx_eqep_hwmod_class,
 	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_eqep2_irqs,
+	.main_clk	= "l4ls_gclk",
+};
+
+/* ehrpwm2 */
+static struct omap_hwmod_irq_info am33xx_ehrpwm2_irqs[] = {
+	{ .name = "int", .irq = 39 + OMAP_INTC_START, },
+	{ .name = "tzint", .irq = 60 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_ehrpwm2_hwmod = {
+	.name		= "ehrpwm2",
+	.class		= &am33xx_ehrpwm_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_ehrpwm2_irqs,
 	.main_clk	= "l4ls_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
 };
 
 /*
@@ -2547,162 +2631,202 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__elm = {
 	.user		= OCP_USER_MPU,
 };
 
-/*
- * Splitting the resources to handle access of PWMSS config space
- * and module specific part independently
- */
-static struct omap_hwmod_addr_space am33xx_ehrpwm0_addr_space[] = {
+static struct omap_hwmod_addr_space am33xx_epwmss0_addr_space[] = {
 	{
 		.pa_start	= 0x48300000,
 		.pa_end		= 0x48300000 + SZ_16 - 1,
 		.flags		= ADDR_TYPE_RT
 	},
-	{
-		.pa_start	= 0x48300200,
-		.pa_end		= 0x48300200 + SZ_256 - 1,
-		.flags		= ADDR_TYPE_RT
-	},
 	{ }
 };
 
-static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm0 = {
+static struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss0 = {
 	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_ehrpwm0_hwmod,
+	.slave		= &am33xx_epwmss0_hwmod,
 	.clk		= "l4ls_gclk",
-	.addr		= am33xx_ehrpwm0_addr_space,
+	.addr		= am33xx_epwmss0_addr_space,
 	.user		= OCP_USER_MPU,
 };
 
-/*
- * Splitting the resources to handle access of PWMSS config space
- * and module specific part independently
- */
-static struct omap_hwmod_addr_space am33xx_ehrpwm1_addr_space[] = {
-	{
-		.pa_start	= 0x48302000,
-		.pa_end		= 0x48302000 + SZ_16 - 1,
-		.flags		= ADDR_TYPE_RT
-	},
+static struct omap_hwmod_addr_space am33xx_ecap0_addr_space[] = {
 	{
-		.pa_start	= 0x48302200,
-		.pa_end		= 0x48302200 + SZ_256 - 1,
-		.flags		= ADDR_TYPE_RT
+		.pa_start	= 0x48300100,
+		.pa_end		= 0x48300100 + SZ_128 - 1,
 	},
 	{ }
 };
 
-static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm1 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_ehrpwm1_hwmod,
+static struct omap_hwmod_ocp_if am33xx_epwmss0__ecap0 = {
+	.master		= &am33xx_epwmss0_hwmod,
+	.slave		= &am33xx_ecap0_hwmod,
 	.clk		= "l4ls_gclk",
-	.addr		= am33xx_ehrpwm1_addr_space,
+	.addr		= am33xx_ecap0_addr_space,
 	.user		= OCP_USER_MPU,
 };
 
-/*
- * Splitting the resources to handle access of PWMSS config space
- * and module specific part independently
- */
-static struct omap_hwmod_addr_space am33xx_ehrpwm2_addr_space[] = {
-	{
-		.pa_start	= 0x48304000,
-		.pa_end		= 0x48304000 + SZ_16 - 1,
-		.flags		= ADDR_TYPE_RT
-	},
+static struct omap_hwmod_addr_space am33xx_eqep0_addr_space[] = {
 	{
-		.pa_start	= 0x48304200,
-		.pa_end		= 0x48304200 + SZ_256 - 1,
-		.flags		= ADDR_TYPE_RT
+		.pa_start	= 0x48300180,
+		.pa_end		= 0x48300180 + SZ_128 - 1,
 	},
 	{ }
 };
 
-static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm2 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_ehrpwm2_hwmod,
+static struct omap_hwmod_ocp_if am33xx_epwmss0__eqep0 = {
+	.master		= &am33xx_epwmss0_hwmod,
+	.slave		= &am33xx_eqep0_hwmod,
 	.clk		= "l4ls_gclk",
-	.addr		= am33xx_ehrpwm2_addr_space,
+	.addr		= am33xx_eqep0_addr_space,
 	.user		= OCP_USER_MPU,
 };
 
-/*
- * Splitting the resources to handle access of PWMSS config space
- * and module specific part independently
- */
-static struct omap_hwmod_addr_space am33xx_ecap0_addr_space[] = {
-	{
-		.pa_start	= 0x48300000,
-		.pa_end		= 0x48300000 + SZ_16 - 1,
-		.flags		= ADDR_TYPE_RT
-	},
+static struct omap_hwmod_addr_space am33xx_ehrpwm0_addr_space[] = {
 	{
-		.pa_start	= 0x48300100,
-		.pa_end		= 0x48300100 + SZ_256 - 1,
-		.flags		= ADDR_TYPE_RT
+		.pa_start	= 0x48300200,
+		.pa_end		= 0x48300200 + SZ_128 - 1,
 	},
 	{ }
 };
 
-static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap0 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_ecap0_hwmod,
+static struct omap_hwmod_ocp_if am33xx_epwmss0__ehrpwm0 = {
+	.master		= &am33xx_epwmss0_hwmod,
+	.slave		= &am33xx_ehrpwm0_hwmod,
 	.clk		= "l4ls_gclk",
-	.addr		= am33xx_ecap0_addr_space,
+	.addr		= am33xx_ehrpwm0_addr_space,
 	.user		= OCP_USER_MPU,
 };
 
-/*
- * Splitting the resources to handle access of PWMSS config space
- * and module specific part independently
- */
-static struct omap_hwmod_addr_space am33xx_ecap1_addr_space[] = {
+
+static struct omap_hwmod_addr_space am33xx_epwmss1_addr_space[] = {
 	{
 		.pa_start	= 0x48302000,
 		.pa_end		= 0x48302000 + SZ_16 - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_epwmss1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_epwmss1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_ecap1_addr_space[] = {
 	{
 		.pa_start	= 0x48302100,
-		.pa_end		= 0x48302100 + SZ_256 - 1,
-		.flags		= ADDR_TYPE_RT
+		.pa_end		= 0x48302100 + SZ_128 - 1,
 	},
 	{ }
 };
 
-static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap1 = {
-	.master		= &am33xx_l4_ls_hwmod,
+static struct omap_hwmod_ocp_if am33xx_epwmss1__ecap1 = {
+	.master		= &am33xx_epwmss1_hwmod,
 	.slave		= &am33xx_ecap1_hwmod,
 	.clk		= "l4ls_gclk",
 	.addr		= am33xx_ecap1_addr_space,
 	.user		= OCP_USER_MPU,
 };
 
-/*
- * Splitting the resources to handle access of PWMSS config space
- * and module specific part independently
- */
-static struct omap_hwmod_addr_space am33xx_ecap2_addr_space[] = {
+static struct omap_hwmod_addr_space am33xx_eqep1_addr_space[] = {
+	{
+		.pa_start	= 0x48302180,
+		.pa_end		= 0x48302180 + SZ_128 - 1,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_epwmss1__eqep1 = {
+	.master		= &am33xx_epwmss1_hwmod,
+	.slave		= &am33xx_eqep1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_eqep1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_ehrpwm1_addr_space[] = {
+	{
+		.pa_start	= 0x48302200,
+		.pa_end		= 0x48302200 + SZ_128 - 1,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_epwmss1__ehrpwm1 = {
+	.master		= &am33xx_epwmss1_hwmod,
+	.slave		= &am33xx_ehrpwm1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_ehrpwm1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_epwmss2_addr_space[] = {
 	{
 		.pa_start	= 0x48304000,
 		.pa_end		= 0x48304000 + SZ_16 - 1,
 		.flags		= ADDR_TYPE_RT
 	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_epwmss2_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_epwmss2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_ecap2_addr_space[] = {
 	{
 		.pa_start	= 0x48304100,
-		.pa_end		= 0x48304100 + SZ_256 - 1,
-		.flags		= ADDR_TYPE_RT
+		.pa_end		= 0x48304100 + SZ_128 - 1,
 	},
 	{ }
 };
 
-static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap2 = {
-	.master		= &am33xx_l4_ls_hwmod,
+static struct omap_hwmod_ocp_if am33xx_epwmss2__ecap2 = {
+	.master		= &am33xx_epwmss2_hwmod,
 	.slave		= &am33xx_ecap2_hwmod,
 	.clk		= "l4ls_gclk",
 	.addr		= am33xx_ecap2_addr_space,
 	.user		= OCP_USER_MPU,
 };
 
+static struct omap_hwmod_addr_space am33xx_eqep2_addr_space[] = {
+	{
+		.pa_start	= 0x48304180,
+		.pa_end		= 0x48304180 + SZ_128 - 1,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_epwmss2__eqep2 = {
+	.master		= &am33xx_epwmss2_hwmod,
+	.slave		= &am33xx_eqep2_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_eqep2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_ehrpwm2_addr_space[] = {
+	{
+		.pa_start	= 0x48304200,
+		.pa_end		= 0x48304200 + SZ_128 - 1,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_epwmss2__ehrpwm2 = {
+	.master		= &am33xx_epwmss2_hwmod,
+	.slave		= &am33xx_ehrpwm2_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_ehrpwm2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
 /* l3s cfg -> gpmc */
 static struct omap_hwmod_addr_space am33xx_gpmc_addr_space[] = {
 	{
@@ -2827,24 +2951,6 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp0 = {
 	.user		= OCP_USER_MPU,
 };
 
-/* l3 s -> mcasp0 data */
-static struct omap_hwmod_addr_space am33xx_mcasp0_data_addr_space[] = {
-	{
-		.pa_start	= 0x46000000,
-		.pa_end		= 0x46000000 + SZ_4M - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l3_s__mcasp0_data = {
-	.master		= &am33xx_l3_s_hwmod,
-	.slave		= &am33xx_mcasp0_hwmod,
-	.clk		= "l3s_gclk",
-	.addr		= am33xx_mcasp0_data_addr_space,
-	.user		= OCP_USER_SDMA,
-};
-
 /* l4 ls -> mcasp1 */
 static struct omap_hwmod_addr_space am33xx_mcasp1_addr_space[] = {
 	{
@@ -2863,24 +2969,6 @@ static struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp1 = {
 	.user		= OCP_USER_MPU,
 };
 
-/* l3 s -> mcasp1 data */
-static struct omap_hwmod_addr_space am33xx_mcasp1_data_addr_space[] = {
-	{
-		.pa_start	= 0x46400000,
-		.pa_end		= 0x46400000 + SZ_4M - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l3_s__mcasp1_data = {
-	.master		= &am33xx_l3_s_hwmod,
-	.slave		= &am33xx_mcasp1_hwmod,
-	.clk		= "l3s_gclk",
-	.addr		= am33xx_mcasp1_data_addr_space,
-	.user		= OCP_USER_SDMA,
-};
-
 /* l4 ls -> mmc0 */
 static struct omap_hwmod_addr_space am33xx_mmc0_addr_space[] = {
 	{
@@ -3328,6 +3416,42 @@ static struct omap_hwmod_ocp_if am33xx_l3_s__usbss = {
 	.flags		= OCPIF_SWSUP_IDLE,
 };
 
+/* l3 main -> sha0 HIB2 */
+static struct omap_hwmod_addr_space am33xx_sha0_addrs[] = {
+	{
+		.pa_start	= 0x53100000,
+		.pa_end		= 0x53100000 + SZ_512 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_main__sha0 = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_sha0_hwmod,
+	.clk		= "sha0_fck",
+	.addr		= am33xx_sha0_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 main -> AES0 HIB2 */
+static struct omap_hwmod_addr_space am33xx_aes0_addrs[] = {
+	{
+		.pa_start	= 0x53500000,
+		.pa_end		= 0x53500000 + SZ_1M - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_main__aes0 = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_aes0_hwmod,
+	.clk		= "aes0_fck",
+	.addr		= am33xx_aes0_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
 	&am33xx_l4_fw__emif_fw,
 	&am33xx_l3_main__emif,
@@ -3365,9 +3489,7 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
 	&am33xx_l4_per__i2c3,
 	&am33xx_l4_per__mailbox,
 	&am33xx_l4_ls__mcasp0,
-	&am33xx_l3_s__mcasp0_data,
 	&am33xx_l4_ls__mcasp1,
-	&am33xx_l3_s__mcasp1_data,
 	&am33xx_l4_ls__mmc0,
 	&am33xx_l4_ls__mmc1,
 	&am33xx_l3_s__mmc2,
@@ -3385,12 +3507,18 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
 	&am33xx_l4_ls__uart6,
 	&am33xx_l4_ls__spinlock,
 	&am33xx_l4_ls__elm,
-	&am33xx_l4_ls__ehrpwm0,
-	&am33xx_l4_ls__ehrpwm1,
-	&am33xx_l4_ls__ehrpwm2,
-	&am33xx_l4_ls__ecap0,
-	&am33xx_l4_ls__ecap1,
-	&am33xx_l4_ls__ecap2,
+	&am33xx_l4_ls__epwmss0,
+	&am33xx_epwmss0__ecap0,
+	&am33xx_epwmss0__eqep0,
+	&am33xx_epwmss0__ehrpwm0,
+	&am33xx_l4_ls__epwmss1,
+	&am33xx_epwmss1__ecap1,
+	&am33xx_epwmss1__eqep1,
+	&am33xx_epwmss1__ehrpwm1,
+	&am33xx_l4_ls__epwmss2,
+	&am33xx_epwmss2__ecap2,
+	&am33xx_epwmss2__eqep2,
+	&am33xx_epwmss2__ehrpwm2,
 	&am33xx_l3_s__gpmc,
 	&am33xx_l3_main__lcdc,
 	&am33xx_l4_ls__mcspi0,
@@ -3401,6 +3529,8 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
 	&am33xx_l3_s__usbss,
 	&am33xx_l4_hs__cpgmac0,
 	&am33xx_cpgmac0__mdio,
+	&am33xx_l3_main__sha0,
+	&am33xx_l3_main__aes0,
 	NULL,
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 8bb2628..85d1b08 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -3540,6 +3540,132 @@ static struct omap_hwmod_ocp_if omap3xxx_l3_main__gpmc = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_core -> SHAM2 (SHA1/MD5) (similar to omap24xx) */
+static struct omap_hwmod_sysc_fields omap3_sham_sysc_fields = {
+	.sidle_shift	= 4,
+	.srst_shift	= 1,
+	.autoidle_shift	= 0,
+};
+
+static struct omap_hwmod_class_sysconfig omap3_sham_sysc = {
+	.rev_offs	= 0x5c,
+	.sysc_offs	= 0x60,
+	.syss_offs	= 0x64,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.sysc_fields	= &omap3_sham_sysc_fields,
+};
+
+static struct omap_hwmod_class omap3xxx_sham_class = {
+	.name	= "sham",
+	.sysc	= &omap3_sham_sysc,
+};
+
+struct omap_hwmod_irq_info omap3_sham_mpu_irqs[] = {
+	{ .irq = 49 + OMAP_INTC_START, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod_dma_info omap3_sham_sdma_reqs[] = {
+	{ .name = "rx", .dma_req = OMAP34XX_DMA_SHA1MD5_RX, },
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod omap3xxx_sham_hwmod = {
+	.name		= "sham",
+	.mpu_irqs	= omap3_sham_mpu_irqs,
+	.sdma_reqs	= omap3_sham_sdma_reqs,
+	.main_clk	= "sha12_ick",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SHA12_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_SHA12_SHIFT,
+		},
+	},
+	.class		= &omap3xxx_sham_class,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_sham_addrs[] = {
+	{
+		.pa_start	= 0x480c3000,
+		.pa_end		= 0x480c3000 + 0x64 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__sham = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_sham_hwmod,
+	.clk		= "sha12_ick",
+	.addr		= omap3xxx_sham_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> AES */
+static struct omap_hwmod_sysc_fields omap3xxx_aes_sysc_fields = {
+	.sidle_shift	= 6,
+	.srst_shift	= 1,
+	.autoidle_shift	= 0,
+};
+
+static struct omap_hwmod_class_sysconfig omap3_aes_sysc = {
+	.rev_offs	= 0x44,
+	.sysc_offs	= 0x48,
+	.syss_offs	= 0x4c,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap3xxx_aes_sysc_fields,
+};
+
+static struct omap_hwmod_class omap3xxx_aes_class = {
+	.name	= "aes",
+	.sysc	= &omap3_aes_sysc,
+};
+
+struct omap_hwmod_dma_info omap3_aes_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP34XX_DMA_AES2_TX, },
+	{ .name = "rx", .dma_req = OMAP34XX_DMA_AES2_RX, },
+	{ .dma_req = -1 }
+};
+
+struct omap_hwmod omap3xxx_aes_hwmod = {
+	.name		= "aes",
+	.sdma_reqs	= omap3_aes_sdma_reqs,
+	.main_clk	= "aes2_ick",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_AES2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_AES2_SHIFT,
+		},
+	},
+	.class		= &omap3xxx_aes_class,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_aes_addrs[] = {
+	{
+		.pa_start	= 0x480c5000,
+		.pa_end		= 0x480c5000 + 0x50 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__aes = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_aes_hwmod,
+	.clk		= "aes2_ick",
+	.addr		= omap3xxx_aes_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l3_main__l4_core,
 	&omap3xxx_l3_main__l4_per,
@@ -3593,6 +3719,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
 /* GP-only hwmod links */
 static struct omap_hwmod_ocp_if *omap3xxx_gp_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l4_sec__timer12,
+	&omap3xxx_l4_core__sham,
+	&omap3xxx_l4_core__aes,
 	NULL
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 793f54a..624a7e8 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -2702,13 +2702,6 @@ static struct resource omap44xx_usb_phy_and_pll_addrs[] = {
 		.end		= 0x4a0ae000,
 		.flags		= IORESOURCE_MEM,
 	},
-	{
-		/* XXX: Remove this once control module driver is in place */
-		.name		= "ctrl_dev",
-		.start		= 0x4a002300,
-		.end		= 0x4a002303,
-		.flags		= IORESOURCE_MEM,
-	},
 	{ }
 };
 
@@ -6156,12 +6149,6 @@ static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
 		.pa_end		= 0x4a0ab7ff,
 		.flags		= ADDR_TYPE_RT
 	},
-	{
-		/* XXX: Remove this once control module driver is in place */
-		.pa_start	= 0x4a00233c,
-		.pa_end		= 0x4a00233f,
-		.flags		= ADDR_TYPE_RT
-	},
 	{ }
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
index cfcce29..6e04ff7 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
@@ -78,6 +78,8 @@ extern struct omap_hwmod omap2xxx_mcspi2_hwmod;
 extern struct omap_hwmod omap2xxx_counter_32k_hwmod;
 extern struct omap_hwmod omap2xxx_gpmc_hwmod;
 extern struct omap_hwmod omap2xxx_rng_hwmod;
+extern struct omap_hwmod omap2xxx_sham_hwmod;
+extern struct omap_hwmod omap2xxx_aes_hwmod;
 
 /* Common interface data across OMAP2xxx */
 extern struct omap_hwmod_ocp_if omap2xxx_l3_main__l4_core;
@@ -105,6 +107,8 @@ extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_dispc;
 extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_rfbi;
 extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_venc;
 extern struct omap_hwmod_ocp_if omap2xxx_l4_core__rng;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__sham;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__aes;
 
 /* Common IP block data */
 extern struct omap_hwmod_dma_info omap2_uart1_sdma_reqs[];
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index e49b40b..4b2b254 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -120,6 +120,41 @@ static struct twl4030_audio_data omap3_audio_pdata = {
 	.codec = &omap3_codec,
 };
 
+static struct twl4030_ins wrst_seq[] __initdata = {
+	{MSG_SINGULAR(DEV_GRP_NULL, 0x1b, RES_STATE_OFF), 2},
+	{MSG_SINGULAR(DEV_GRP_P1, 0xf, RES_STATE_WRST), 15},
+	{MSG_SINGULAR(DEV_GRP_P1, 0x10, RES_STATE_WRST), 15},
+	{MSG_SINGULAR(DEV_GRP_P1, 0x7, RES_STATE_WRST), 0x60},
+	{MSG_SINGULAR(DEV_GRP_P1, 0x19, RES_STATE_ACTIVE), 2},
+	{MSG_SINGULAR(DEV_GRP_NULL, 0x1b, RES_STATE_ACTIVE), 2},
+};
+
+static struct twl4030_script wrst_script __initdata = {
+	.script = wrst_seq,
+	.size	= ARRAY_SIZE(wrst_seq),
+	.flags	= TWL4030_WRST_SCRIPT,
+};
+
+static struct twl4030_script *omap3_power_scripts[] __initdata = {
+	&wrst_script,
+};
+
+static struct twl4030_resconfig omap3_rconfig[] = {
+	{ .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P3, .type = -1,
+		.type2 = -1 },
+	{ .resource = RES_VDD1, .devgroup = DEV_GRP_P1, .type = -1,
+		.type2 = -1 },
+	{ .resource = RES_VDD2, .devgroup = DEV_GRP_P1, .type = -1,
+		.type2 = -1 },
+	{ 0, 0},
+};
+
+static struct twl4030_power_data omap3_power_pdata = {
+	.scripts	= omap3_power_scripts,
+	.num		= ARRAY_SIZE(omap3_power_scripts),
+	.resource_config = omap3_rconfig,
+};
+
 static struct regulator_consumer_supply omap3_vdda_dac_supplies[] = {
 	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
 };
@@ -224,6 +259,9 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 	if (pdata_flags & TWL_COMMON_PDATA_AUDIO && !pmic_data->audio)
 		pmic_data->audio = &omap3_audio_pdata;
 
+	if (pdata_flags & TWL_COMMON_PDATA_POWER && !pmic_data->power)
+		pmic_data->power = &omap3_power_pdata;
+
 	/* Common regulator configurations */
 	if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
 		pmic_data->vdac = &omap3_vdac_idata;
@@ -360,6 +398,7 @@ static struct regulator_init_data omap4_vusb_idata = {
 static struct regulator_init_data omap4_clk32kg_idata = {
 	.constraints = {
 		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
+		.always_on		= true,
 	},
 };
 
diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h
index dcfbad5..dbeb905 100644
--- a/arch/arm/mach-omap2/twl-common.h
+++ b/arch/arm/mach-omap2/twl-common.h
@@ -7,6 +7,7 @@
 #define TWL_COMMON_PDATA_BCI		(1 << 1)
 #define TWL_COMMON_PDATA_MADC		(1 << 2)
 #define TWL_COMMON_PDATA_AUDIO		(1 << 3)
+#define TWL_COMMON_PDATA_POWER		(1 << 4)
 
 /* Common LDO regulators for TWL4030/TWL6030 */
 #define TWL_COMMON_REGULATOR_VDAC	(1 << 0)
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 7b33b37..9d27e3f 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -85,6 +85,9 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
 	musb_plat.mode = board_data->mode;
 	musb_plat.extvbus = board_data->extvbus;
 
+	if (cpu_is_omap44xx())
+		musb_plat.has_mailbox = true;
+
 	if (soc_is_am35xx()) {
 		oh_name = "am35x_otg_hs";
 		name = "musb-am35x";
diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index c5a3c6f..e832bc7 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/err.h>
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -26,6 +27,24 @@
 static u8		async_cs, sync_cs;
 static unsigned		refclk_psec;
 
+static struct gpmc_settings tusb_async = {
+	.wait_on_read	= true,
+	.wait_on_write	= true,
+	.device_width	= GPMC_DEVWIDTH_16BIT,
+	.mux_add_data	= GPMC_MUX_AD,
+};
+
+static struct gpmc_settings tusb_sync = {
+	.burst_read	= true,
+	.burst_write	= true,
+	.sync_read	= true,
+	.sync_write	= true,
+	.wait_on_read	= true,
+	.wait_on_write	= true,
+	.burst_len	= GPMC_BURST_16,
+	.device_width	= GPMC_DEVWIDTH_16BIT,
+	.mux_add_data	= GPMC_MUX_AD,
+};
 
 /* NOTE:  timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
 
@@ -37,8 +56,6 @@ static int tusb_set_async_mode(unsigned sysclk_ps)
 
 	memset(&dev_t, 0, sizeof(dev_t));
 
-	dev_t.mux = true;
-
 	dev_t.t_ceasu = 8 * 1000;
 	dev_t.t_avdasu = t_acsnh_advnh - 7000;
 	dev_t.t_ce_avd = 1000;
@@ -52,7 +69,7 @@ static int tusb_set_async_mode(unsigned sysclk_ps)
 	dev_t.t_wpl = 300;
 	dev_t.cyc_aavdh_we = 1;
 
-	gpmc_calc_timings(&t, &dev_t);
+	gpmc_calc_timings(&t, &tusb_async, &dev_t);
 
 	return gpmc_cs_set_timings(async_cs, &t);
 }
@@ -65,10 +82,6 @@ static int tusb_set_sync_mode(unsigned sysclk_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;
@@ -84,7 +97,7 @@ static int tusb_set_sync_mode(unsigned sysclk_ps)
 	dev_t.cyc_wpl = 6;
 	dev_t.t_ce_rdyz = 7000;
 
-	gpmc_calc_timings(&t, &dev_t);
+	gpmc_calc_timings(&t, &tusb_sync, &dev_t);
 
 	return gpmc_cs_set_timings(sync_cs, &t);
 }
@@ -165,18 +178,12 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 		return status;
 	}
 	tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
+	tusb_async.wait_pin = waitpin;
 	async_cs = async;
-	gpmc_cs_write_reg(async, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_PAGE_LEN(2)
-			| GPMC_CONFIG1_WAIT_READ_MON
-			| GPMC_CONFIG1_WAIT_WRITE_MON
-			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
-			| GPMC_CONFIG1_READTYPE_ASYNC
-			| GPMC_CONFIG1_WRITETYPE_ASYNC
-			| GPMC_CONFIG1_DEVICESIZE_16
-			| GPMC_CONFIG1_DEVICETYPE_NOR
-			| GPMC_CONFIG1_MUXADDDATA);
 
+	status = gpmc_cs_program_settings(async_cs, &tusb_async);
+	if (status < 0)
+		return status;
 
 	/* SYNC region, primarily for DMA */
 	status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
@@ -186,21 +193,12 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 		return status;
 	}
 	tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
+	tusb_sync.wait_pin = waitpin;
 	sync_cs = sync;
-	gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_READMULTIPLE_SUPP
-			| GPMC_CONFIG1_READTYPE_SYNC
-			| GPMC_CONFIG1_WRITEMULTIPLE_SUPP
-			| GPMC_CONFIG1_WRITETYPE_SYNC
-			| GPMC_CONFIG1_PAGE_LEN(2)
-			| GPMC_CONFIG1_WAIT_READ_MON
-			| GPMC_CONFIG1_WAIT_WRITE_MON
-			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
-			| GPMC_CONFIG1_DEVICESIZE_16
-			| GPMC_CONFIG1_DEVICETYPE_NOR
-			| GPMC_CONFIG1_MUXADDDATA
-			/* fclk divider gets set later */
-			);
+
+	status = gpmc_cs_program_settings(sync_cs, &tusb_sync);
+	if (status < 0)
+		return status;
 
 	/* IRQ */
 	status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq");
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 665870d..0b81d6c 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -29,6 +29,7 @@ config ARCH_OMAP2PLUS
 	select PINCTRL
 	select PROC_DEVICETREE if PROC_FS
 	select SPARSE_IRQ
+	select TI_PRIV_EDMA
 	select USE_OF
 	help
 	  "Systems based on OMAP2, OMAP3, OMAP4 or OMAP5"
diff --git a/defconfig b/defconfig
new file mode 100644
index 0000000..8902d3f
--- /dev/null
+++ b/defconfig
@@ -0,0 +1,3972 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 3.8.0-rc3 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_FHANDLE is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_IRQ_DOMAIN=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+CONFIG_SPARSE_IRQ=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_RCU_FANOUT=32
+CONFIG_RCU_FANOUT_LEAF=16
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_RCU_FAST_NO_HZ is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_NOCB_CPU is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_RESOURCE_COUNTERS is not set
+# CONFIG_CGROUP_PERF is not set
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_CFS_BANDWIDTH is not set
+# CONFIG_RT_GROUP_SCHED is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_SCHED_AUTOGROUP=y
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+CONFIG_HAVE_UID16=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+# CONFIG_JUMP_LABEL is not set
+CONFIG_KRETPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_CLONE_BACKWARDS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_MODULE_SIG is not set
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_BLK_DEV_INTEGRITY=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_PADATA=y
+CONFIG_ASN1=m
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM2835 is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXS is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_VT8500_SINGLE is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+
+#
+# TI OMAP Common Features
+#
+# CONFIG_ARCH_OMAP1 is not set
+CONFIG_ARCH_OMAP2PLUS=y
+
+#
+# OMAP Feature Selections
+#
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_32K_TIMER=y
+# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set
+CONFIG_OMAP_32K_TIMER_HZ=512
+CONFIG_OMAP_DM_TIMER=y
+CONFIG_OMAP_PM_NOOP=y
+CONFIG_MACH_OMAP_GENERIC=y
+
+#
+# TI OMAP2/3/4 Specific Features
+#
+CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
+CONFIG_SOC_HAS_OMAP2_SDRC=y
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+CONFIG_ARCH_OMAP4=y
+# CONFIG_SOC_OMAP5 is not set
+CONFIG_SOC_OMAP3430=y
+# CONFIG_SOC_TI81XX is not set
+CONFIG_SOC_AM33XX=y
+CONFIG_OMAP_PACKAGE_CBB=y
+CONFIG_OMAP_PACKAGE_CBL=y
+CONFIG_OMAP_PACKAGE_CBS=y
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_AM335XEVM=y
+CONFIG_MACH_AM335XIAEVM=y
+CONFIG_MACH_TAM335X=y
+CONFIG_MACH_OMAP3_BEAGLE=y
+# CONFIG_MACH_DEVKIT8000 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP3530_LV_SOM is not set
+# CONFIG_MACH_OMAP3_TORPEDO is not set
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3EVM is not set
+# CONFIG_MACH_OMAP3517EVM is not set
+# CONFIG_MACH_CRANEBOARD is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+# CONFIG_MACH_TOUCHBOOK is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_NOKIA_RM680 is not set
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_ZOOM2 is not set
+# CONFIG_MACH_OMAP_ZOOM3 is not set
+# CONFIG_MACH_CM_T35 is not set
+# CONFIG_MACH_CM_T3517 is not set
+CONFIG_MACH_IGEP0020=y
+# CONFIG_MACH_IGEP0030 is not set
+# CONFIG_MACH_SBC3530 is not set
+# CONFIG_MACH_OMAP_3630SDP is not set
+# CONFIG_MACH_OMAP_4430SDP is not set
+CONFIG_MACH_OMAP4_PANDA=y
+# CONFIG_OMAP3_EMU is not set
+# CONFIG_OMAP3_SDRC_AC_TIMING is not set
+# CONFIG_OMAP4_ERRATA_I688 is not set
+# CONFIG_ARCH_VT8500 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_ARM_VIRT_EXT is not set
+CONFIG_SWP_EMULATE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_OUTER_CACHE=y
+CONFIG_OUTER_CACHE_SYNC=y
+CONFIG_CACHE_L2X0=y
+CONFIG_CACHE_PL310=y
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+CONFIG_ARM_NR_BANKS=8
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+# CONFIG_ARM_ERRATA_742230 is not set
+# CONFIG_ARM_ERRATA_742231 is not set
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_PL310_ERRATA_727915=y
+# CONFIG_ARM_ERRATA_743622 is not set
+# CONFIG_ARM_ERRATA_751472 is not set
+# CONFIG_PL310_ERRATA_753970 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_754327 is not set
+# CONFIG_ARM_ERRATA_764369 is not set
+# CONFIG_PL310_ERRATA_769419 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+CONFIG_ARM_GIC=y
+CONFIG_TI_PRIV_EDMA=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+CONFIG_SMP=y
+CONFIG_SMP_ON_UP=y
+CONFIG_ARM_CPU_TOPOLOGY=y
+# CONFIG_SCHED_MC is not set
+# CONFIG_SCHED_SMT is not set
+CONFIG_HAVE_ARM_SCU=y
+# CONFIG_ARM_ARCH_TIMER is not set
+CONFIG_HAVE_ARM_TWD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_NR_CPUS=4
+CONFIG_HOTPLUG_CPU=y
+CONFIG_LOCAL_TIMERS=y
+CONFIG_ARCH_NR_GPIO=0
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=512
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HIGHMEM=y
+# CONFIG_HIGHPTE is not set
+CONFIG_HW_PERF_EVENTS=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_COMPACTION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_FRONTSWAP is not set
+CONFIG_FORCE_MAX_ZONEORDER=12
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_AUTO_ZRELADDR is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_GENERIC_CPUFREQ_CPU0=y
+
+#
+# ARM CPU frequency scaling drivers
+#
+# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set
+# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set
+# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set
+# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set
+CONFIG_CPU_IDLE=y
+# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+# CONFIG_COREDUMP is not set
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_ADVANCED_DEBUG is not set
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_PM_SLEEP_DEBUG=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_HAS_OPP=y
+CONFIG_PM_OPP=y
+CONFIG_PM_CLK=y
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_IPVTI is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_INET_UDP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_GRE=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+# CONFIG_NETFILTER_XT_MARK is not set
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_HL=m
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+# CONFIG_NETFILTER_XT_TARGET_LOG is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+CONFIG_NETFILTER_XT_MATCH_ECN=m
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+CONFIG_NETFILTER_XT_MATCH_HL=m
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_IPV6 is not set
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+# CONFIG_IP_VS_PROTO_TCP is not set
+# CONFIG_IP_VS_PROTO_UDP is not set
+# CONFIG_IP_VS_PROTO_AH_ESP is not set
+# CONFIG_IP_VS_PROTO_ESP is not set
+# CONFIG_IP_VS_PROTO_AH is not set
+# CONFIG_IP_VS_PROTO_SCTP is not set
+
+#
+# IPVS scheduler
+#
+# CONFIG_IP_VS_RR is not set
+# CONFIG_IP_VS_WRR is not set
+# CONFIG_IP_VS_LC is not set
+# CONFIG_IP_VS_WLC is not set
+# CONFIG_IP_VS_LBLC is not set
+# CONFIG_IP_VS_LBLCR is not set
+# CONFIG_IP_VS_DH is not set
+# CONFIG_IP_VS_SH is not set
+# CONFIG_IP_VS_SED is not set
+# CONFIG_IP_VS_NQ is not set
+
+#
+# IPVS SH scheduler
+#
+CONFIG_IP_VS_SH_TAB_BITS=8
+
+#
+# IPVS application helper
+#
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV6 is not set
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+# CONFIG_L2TP_V3 is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+CONFIG_HAVE_NET_DSA=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_WAN_ROUTER is not set
+CONFIG_PHONET=m
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFB is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_CHOKE is not set
+# CONFIG_NET_SCH_QFQ is not set
+CONFIG_NET_SCH_CODEL=y
+CONFIG_NET_SCH_FQ_CODEL=y
+# CONFIG_NET_SCH_PLUG is not set
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+CONFIG_NET_CLS_CGROUP=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_BLA=y
+# CONFIG_BATMAN_ADV_DAT is not set
+# CONFIG_BATMAN_ADV_DEBUG is not set
+CONFIG_OPENVSWITCH=m
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+CONFIG_NETPRIO_CGROUP=m
+CONFIG_BQL=y
+CONFIG_BPF_JIT=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+CONFIG_CAN_GW=m
+
+#
+# CAN Device Drivers
+#
+# CONFIG_CAN_VCAN is not set
+# CONFIG_CAN_SLCAN is not set
+CONFIG_CAN_DEV=m
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_TI_HECC=m
+CONFIG_CAN_MCP251X=m
+# CONFIG_CAN_GRCAN is not set
+# CONFIG_CAN_SJA1000 is not set
+CONFIG_CAN_C_CAN=m
+CONFIG_CAN_C_CAN_PLATFORM=m
+# CONFIG_CAN_CC770 is not set
+
+#
+# CAN USB interfaces
+#
+CONFIG_CAN_EMS_USB=m
+CONFIG_CAN_ESD_USB2=m
+# CONFIG_CAN_KVASER_USB is not set
+CONFIG_CAN_PEAK_USB=m
+# CONFIG_CAN_SOFTING is not set
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+# CONFIG_IRNET is not set
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+# CONFIG_SIGMATEL_FIR is not set
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIUART_3WIRE=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
+CONFIG_BT_ATH3K=m
+# CONFIG_BT_WILINK is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_CFG80211_DEBUGFS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+CONFIG_MAC80211_MESH=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_MAC80211_DEBUGFS=y
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+CONFIG_RFKILL=m
+CONFIG_RFKILL_LEDS=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_REGULATOR=m
+CONFIG_RFKILL_GPIO=m
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+# CONFIG_NET_9P_DEBUG is not set
+# CONFIG_CAIF is not set
+CONFIG_CEPH_LIB=m
+# CONFIG_CEPH_LIB_PRETTYDEBUG is not set
+# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set
+CONFIG_NFC=m
+CONFIG_NFC_NCI=m
+CONFIG_NFC_HCI=m
+CONFIG_NFC_SHDLC=y
+# CONFIG_NFC_LLCP is not set
+
+#
+# Near Field Communication (NFC) devices
+#
+CONFIG_PN544_HCI_NFC=m
+CONFIG_NFC_PN533=m
+# CONFIG_NFC_WILINK is not set
+CONFIG_HAVE_BPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_CMA is not set
+
+#
+# Bus devices
+#
+CONFIG_OMAP_OCP2SCP=y
+CONFIG_OMAP_INTERCONNECT=y
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_SWAP is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_PHYSMAP_OF is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_DENALI is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+# CONFIG_MTD_NAND_OMAP_BCH is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+CONFIG_MTD_UBI_FASTMAP=y
+# CONFIG_MTD_UBI_GLUEBI is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+
+#
+# Device Tree and Open Firmware support
+#
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_OF_SELFTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_DYNAMIC=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_DEVICE=y
+CONFIG_OF_I2C=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_MTD=y
+CONFIG_OF_DISPLAY_TIMINGS=y
+CONFIG_OF_RESOLVE=y
+CONFIG_OF_OVERLAY=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+CONFIG_VIRTIO_BLK=m
+# CONFIG_BLK_DEV_RBD is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_ATMEL_PWM is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+CONFIG_SENSORS_TSL2550=m
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+CONFIG_BMP085=y
+CONFIG_BMP085_I2C=m
+# CONFIG_BMP085_SPI is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_GPEVT is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+CONFIG_EEPROM_93CX6=y
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+CONFIG_TI_ST=m
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+CONFIG_CAPE_BEAGLEBONE=y
+CONFIG_CAPE_BEAGLEBONE_GEIGER=y
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_VIRTIO=m
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_BLK_DEV_DM is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_MII=y
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+CONFIG_VXLAN=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+CONFIG_VIRTIO_NET=m
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6060 is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+# CONFIG_NET_DSA_MV88E6131 is not set
+# CONFIG_NET_DSA_MV88E6123_61_65 is not set
+CONFIG_ETHERNET=y
+CONFIG_NET_CADENCE=y
+# CONFIG_ARM_AT91_ETHER is not set
+# CONFIG_MACB is not set
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_NET_CALXEDA_XGMAC is not set
+CONFIG_NET_VENDOR_CIRRUS=y
+# CONFIG_CS89x0 is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_FARADAY=y
+# CONFIG_FTMAC100 is not set
+# CONFIG_FTGMAC100 is not set
+CONFIG_NET_VENDOR_INTEL=y
+CONFIG_NET_VENDOR_I825XX=y
+CONFIG_NET_VENDOR_MARVELL=y
+# CONFIG_MVMDIO is not set
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8842 is not set
+CONFIG_KS8851=y
+CONFIG_KS8851_MLL=y
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_AX88796 is not set
+# CONFIG_ETHOC is not set
+CONFIG_NET_VENDOR_SEEQ=y
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_VENDOR_SMSC=y
+CONFIG_SMC91X=y
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
+# CONFIG_SMSC911X_ARCH_HOOKS is not set
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_TI=y
+CONFIG_TI_DAVINCI_EMAC=y
+CONFIG_TI_DAVINCI_MDIO=y
+CONFIG_TI_DAVINCI_CPDMA=y
+CONFIG_TI_CPSW=y
+# CONFIG_TI_CPTS is not set
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_AT803X_PHY=y
+# CONFIG_AMD_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_MDIO_BUS_MUX=m
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+CONFIG_MDIO_BUS_MUX_MMIOREG=m
+# CONFIG_MICREL_KS8995MA is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
+CONFIG_USB_NET_CDC_NCM=y
+# CONFIG_USB_NET_CDC_MBIM is not set
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_SMSC75XX is not set
+CONFIG_USB_NET_SMSC95XX=y
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=y
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_NET_CX82310_ETH is not set
+# CONFIG_USB_NET_KALMIA is not set
+# CONFIG_USB_NET_QMI_WWAN is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_USB_CDC_PHONET is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_USB_SIERRA_NET is not set
+# CONFIG_USB_VL600 is not set
+CONFIG_WLAN=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AT76C50X_USB is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_ATH_CARDS is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_BRCMFMAC is not set
+# CONFIG_HOSTAP is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+# CONFIG_LIBERTAS_SPI is not set
+CONFIG_LIBERTAS_DEBUG=y
+# CONFIG_LIBERTAS_MESH is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_RTL8192CU is not set
+# CONFIG_WL_TI is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_MWIFIEX is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+CONFIG_INPUT_MATRIXKMAP=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+CONFIG_KEYBOARD_TWL4030=y
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
+# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set
+# CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_EGALAX is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_ILI210X is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_WACOM_I2C is not set
+# CONFIG_TOUCHSCREEN_MAX11801 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+CONFIG_TOUCHSCREEN_MMS114=m
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+CONFIG_TOUCHSCREEN_TI_AM335X_TSC=y
+# CONFIG_TOUCHSCREEN_PIXCIR is not set
+CONFIG_TOUCHSCREEN_WM97XX=m
+CONFIG_TOUCHSCREEN_WM9705=y
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_WM9713=y
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC_SERIO is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_TOUCHSCREEN_ST1232 is not set
+# CONFIG_TOUCHSCREEN_TPS6507X is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+# CONFIG_INPUT_TWL4030_VIBRA is not set
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_PWM_BEEPER is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+# CONFIG_SERIAL_8250_DW is not set
+# CONFIG_SERIAL_8250_EM is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
+CONFIG_SERIAL_OMAP=y
+CONFIG_SERIAL_OMAP_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_TTY_PRINTK is not set
+CONFIG_HVC_DRIVER=y
+# CONFIG_HVC_DCC is not set
+CONFIG_VIRTIO_CONSOLE=m
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_HW_RANDOM_ATMEL is not set
+CONFIG_HW_RANDOM_VIRTIO=m
+# CONFIG_HW_RANDOM_EXYNOS is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+CONFIG_SPI_OMAP24XX=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+CONFIG_SPI_SC18IS602=m
+CONFIG_SPI_XCOMM=m
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+# CONFIG_PTP_1588_CLOCK_PCH is not set
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+CONFIG_PINCTRL_SINGLE=y
+# CONFIG_PINCTRL_EXYNOS4 is not set
+# CONFIG_PINCTRL_EXYNOS5440 is not set
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_TS5500 is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+CONFIG_GPIO_TWL4030=y
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_74X164 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+
+#
+# USB GPIO expanders:
+#
+CONFIG_W1=y
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_MASTER_DS1WM=m
+CONFIG_W1_MASTER_GPIO=y
+CONFIG_HDQ_MASTER_OMAP=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=y
+CONFIG_W1_SLAVE_SMEM=y
+CONFIG_W1_SLAVE_DS2408=m
+CONFIG_W1_SLAVE_DS2423=m
+CONFIG_W1_SLAVE_DS2431=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_W1_SLAVE_DS2780=m
+CONFIG_W1_SLAVE_DS2781=m
+CONFIG_W1_SLAVE_DS28E04=m
+CONFIG_W1_SLAVE_BQ27000=m
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+CONFIG_GENERIC_ADC_BATTERY=m
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_ISP1704 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_TWL4030 is not set
+# CONFIG_CHARGER_LP8727 is not set
+CONFIG_CHARGER_GPIO=m
+# CONFIG_CHARGER_MANAGER is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7314 is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+CONFIG_SENSORS_ADT7410=m
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+CONFIG_SENSORS_GPIO_FAN=m
+CONFIG_SENSORS_HIH6130=m
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_LM95245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX1668 is not set
+CONFIG_SENSORS_MAX197=m
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_MCP3021 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_PMBUS is not set
+# CONFIG_SENSORS_SHT15 is not set
+CONFIG_SENSORS_SHT21=m
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SCH56XX_COMMON is not set
+# CONFIG_SENSORS_SCH5627 is not set
+# CONFIG_SENSORS_SCH5636 is not set
+# CONFIG_SENSORS_ADS1015 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_ADS7871 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_INA2XX is not set
+# CONFIG_SENSORS_THMC50 is not set
+CONFIG_SENSORS_TMP102=m
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_FAIR_SHARE is not set
+CONFIG_STEP_WISE=y
+# CONFIG_USER_SPACE is not set
+CONFIG_CPU_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_CORE=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MPCORE_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+CONFIG_TWL4030_WATCHDOG=y
+# CONFIG_MAX63XX_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+CONFIG_MFD_TI_AM335X_TSCADC=y
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_UCB1400_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+CONFIG_MFD_TPS65217=y
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_MADC is not set
+CONFIG_TWL4030_POWER=y
+# CONFIG_MFD_TWL4030_AUDIO is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+CONFIG_MFD_WL1273_CORE=m
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_AS3711 is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+CONFIG_REGULATOR_DUMMY=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_GPIO is not set
+# CONFIG_REGULATOR_AD5398 is not set
+# CONFIG_REGULATOR_FAN53555 is not set
+# CONFIG_REGULATOR_ISL6271A is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8649 is not set
+# CONFIG_REGULATOR_MAX8660 is not set
+# CONFIG_REGULATOR_MAX8952 is not set
+# CONFIG_REGULATOR_MAX8973 is not set
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_LP3972 is not set
+# CONFIG_REGULATOR_LP872X is not set
+# CONFIG_REGULATOR_TPS51632 is not set
+# CONFIG_REGULATOR_TPS62360 is not set
+CONFIG_REGULATOR_TPS65023=y
+CONFIG_REGULATOR_TPS6507X=y
+CONFIG_REGULATOR_TPS65217=y
+# CONFIG_REGULATOR_TPS6524X is not set
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_RADIO_SUPPORT=y
+CONFIG_MEDIA_RC_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_VIDEO_V4L2=m
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_TUNER=m
+CONFIG_V4L2_MEM2MEM_DEV=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DMA_CONTIG=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEOBUF2_CORE=m
+CONFIG_VIDEOBUF2_MEMOPS=m
+CONFIG_VIDEOBUF2_VMALLOC=m
+CONFIG_DVB_CORE=m
+CONFIG_DVB_NET=y
+CONFIG_DVB_MAX_ADAPTERS=8
+CONFIG_DVB_DYNAMIC_MINORS=y
+
+#
+# Media drivers
+#
+CONFIG_RC_CORE=m
+CONFIG_RC_MAP=m
+CONFIG_RC_DECODERS=y
+CONFIG_LIRC=m
+CONFIG_IR_LIRC_CODEC=m
+CONFIG_IR_NEC_DECODER=m
+CONFIG_IR_RC5_DECODER=m
+CONFIG_IR_RC6_DECODER=m
+CONFIG_IR_JVC_DECODER=m
+CONFIG_IR_SONY_DECODER=m
+CONFIG_IR_RC5_SZ_DECODER=m
+CONFIG_IR_SANYO_DECODER=m
+CONFIG_IR_MCE_KBD_DECODER=m
+CONFIG_RC_DEVICES=y
+CONFIG_RC_ATI_REMOTE=m
+CONFIG_IR_IMON=m
+CONFIG_IR_MCEUSB=m
+CONFIG_IR_REDRAT3=m
+CONFIG_IR_STREAMZAP=m
+CONFIG_IR_IGUANA=m
+CONFIG_IR_TTUSBIR=m
+# CONFIG_IR_RX51 is not set
+CONFIG_RC_LOOPBACK=m
+CONFIG_IR_GPIO_CIR=m
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+CONFIG_USB_GSPCA_JL2005BCD=m
+CONFIG_USB_GSPCA_KINECT=m
+CONFIG_USB_GSPCA_KONICA=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_NW80X=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SE401=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_SPCA1528=m
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+CONFIG_USB_GSPCA_SQ930X=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TOPRO=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_VICAM=m
+CONFIG_USB_GSPCA_XIRLINK_CIT=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
+CONFIG_VIDEO_CPIA2=m
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_USB_SN9C102=m
+
+#
+# Analog TV USB devices
+#
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_TLG2300=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_STK1160=m
+CONFIG_VIDEO_STK1160_AC97=y
+
+#
+# Analog/digital TV USB devices
+#
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_RC=y
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_VIDEO_TM6000=m
+CONFIG_VIDEO_TM6000_ALSA=m
+CONFIG_VIDEO_TM6000_DVB=m
+
+#
+# Digital TV USB devices
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_PCTV452E=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_FRIIO=m
+CONFIG_DVB_USB_AZ6027=m
+CONFIG_DVB_USB_TECHNISAT_USB2=m
+CONFIG_DVB_USB_V2=m
+CONFIG_DVB_USB_CYPRESS_FIRMWARE=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_AF9035=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_AZ6007=m
+CONFIG_DVB_USB_CE6230=m
+CONFIG_DVB_USB_EC168=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_IT913X=m
+CONFIG_DVB_USB_LME2510=m
+CONFIG_DVB_USB_MXL111SF=m
+CONFIG_DVB_USB_RTL28XXU=m
+# CONFIG_SMS_USB_DRV is not set
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_EM28XX_RC=m
+CONFIG_TTPCI_EEPROM=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_VPSS_SYSTEM=m
+CONFIG_VIDEO_VPFE_CAPTURE=m
+CONFIG_VIDEO_DM6446_CCDC=m
+CONFIG_VIDEO_OMAP2_VOUT_VRFB=y
+CONFIG_VIDEO_OMAP2_VOUT=m
+# CONFIG_VIDEO_TIMBERDALE is not set
+CONFIG_SOC_CAMERA=m
+CONFIG_SOC_CAMERA_PLATFORM=m
+# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set
+CONFIG_V4L_TEST_DRIVERS=y
+CONFIG_VIDEO_VIVI=m
+CONFIG_VIDEO_MEM2MEM_TESTDEV=m
+
+#
+# Supported MMC/SDIO adapters
+#
+# CONFIG_SMS_SDIO_DRV is not set
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_RADIO_SI470X=y
+CONFIG_USB_SI470X=m
+CONFIG_I2C_SI470X=m
+CONFIG_USB_MR800=m
+CONFIG_USB_DSBR=m
+# CONFIG_RADIO_SHARK is not set
+CONFIG_RADIO_SHARK2=m
+CONFIG_I2C_SI4713=m
+CONFIG_RADIO_SI4713=m
+CONFIG_USB_KEENE=m
+CONFIG_RADIO_TEA5764=m
+CONFIG_RADIO_SAA7706H=m
+CONFIG_RADIO_TEF6862=m
+CONFIG_RADIO_WL1273=m
+
+#
+# Texas Instruments WL128x FM driver (ST based)
+#
+CONFIG_RADIO_WL128X=m
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, frontends)
+#
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_IR_I2C=m
+
+#
+# Audio decoders, processors and mixers
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_CX25840=m
+
+#
+# MPEG video encoders
+#
+CONFIG_VIDEO_CX2341X=m
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+CONFIG_VIDEO_MT9V011=m
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Miscelaneous helper chips
+#
+
+#
+# Sensors used on soc_camera driver
+#
+
+#
+# soc_camera sensor drivers
+#
+# CONFIG_SOC_CAMERA_IMX074 is not set
+CONFIG_SOC_CAMERA_MT9M001=m
+CONFIG_SOC_CAMERA_MT9M111=m
+CONFIG_SOC_CAMERA_MT9T031=m
+CONFIG_SOC_CAMERA_MT9T112=m
+CONFIG_SOC_CAMERA_MT9V022=m
+# CONFIG_SOC_CAMERA_OV2640 is not set
+# CONFIG_SOC_CAMERA_OV5642 is not set
+# CONFIG_SOC_CAMERA_OV6650 is not set
+# CONFIG_SOC_CAMERA_OV772X is not set
+# CONFIG_SOC_CAMERA_OV9640 is not set
+# CONFIG_SOC_CAMERA_OV9740 is not set
+# CONFIG_SOC_CAMERA_RJ54N1 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2063=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_XC4000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_MEDIA_TUNER_MAX2165=m
+CONFIG_MEDIA_TUNER_TDA18218=m
+CONFIG_MEDIA_TUNER_FC0011=m
+CONFIG_MEDIA_TUNER_FC0012=m
+CONFIG_MEDIA_TUNER_FC0013=m
+CONFIG_MEDIA_TUNER_TDA18212=m
+CONFIG_MEDIA_TUNER_E4000=m
+CONFIG_MEDIA_TUNER_FC2580=m
+CONFIG_MEDIA_TUNER_TUA9001=m
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+CONFIG_DVB_STV090x=m
+CONFIG_DVB_STV6110x=m
+
+#
+# Multistandard (cable + terrestrial) frontends
+#
+CONFIG_DVB_DRXK=m
+CONFIG_DVB_TDA18271C2DD=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_ZL10039=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_STV6110=m
+CONFIG_DVB_STV0900=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+CONFIG_DVB_DS3000=m
+CONFIG_DVB_TDA10071=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRXD=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+CONFIG_DVB_AF9013=m
+CONFIG_DVB_EC100=m
+CONFIG_DVB_CXD2820R=m
+CONFIG_DVB_RTL2830=m
+CONFIG_DVB_RTL2832=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3305=m
+CONFIG_DVB_LG2160=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_AU8522_DTV=m
+CONFIG_DVB_AU8522_V4L=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+CONFIG_DVB_DIB8000=m
+CONFIG_DVB_MB86A20S=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+CONFIG_DVB_TUNER_DIB0090=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_LNBP22=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_ISL6423=m
+CONFIG_DVB_A8293=m
+CONFIG_DVB_LGS8GXX=m
+CONFIG_DVB_ATBM8830=m
+CONFIG_DVB_IX2505V=m
+CONFIG_DVB_IT913X_FE=m
+CONFIG_DVB_M88RS2000=m
+CONFIG_DVB_AF9033=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+CONFIG_DRM=y
+CONFIG_DRM_KMS_HELPER=y
+# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
+CONFIG_DRM_GEM_CMA_HELPER=y
+CONFIG_DRM_KMS_CMA_HELPER=y
+
+#
+# I2C encoder or helper chips
+#
+# CONFIG_DRM_I2C_CH7006 is not set
+# CONFIG_DRM_I2C_SIL164 is not set
+# CONFIG_DRM_UDL is not set
+CONFIG_DRM_LCDC=y
+
+#
+# I2C encoder or helper chips
+#
+CONFIG_DRM_I2C_NXP_TDA998X=y
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_DISPLAY_TIMING=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_CFB_REV_PIXELS_IN_BYTE=y
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_BOTH_ENDIAN=y
+# CONFIG_FB_BIG_ENDIAN is not set
+# CONFIG_FB_LITTLE_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=y
+# CONFIG_FB_WMT_GE_ROPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_TMIO is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+CONFIG_FB_DA8XX=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+CONFIG_FB_ST7735=y
+CONFIG_OMAP2_VRFB=y
+CONFIG_OMAP2_DSS=m
+# CONFIG_OMAP2_DSS_DEBUG is not set
+# CONFIG_OMAP2_DSS_DEBUGFS is not set
+CONFIG_OMAP2_DSS_DPI=y
+CONFIG_OMAP2_DSS_RFBI=y
+CONFIG_OMAP2_DSS_VENC=y
+CONFIG_OMAP4_DSS_HDMI=y
+CONFIG_OMAP2_DSS_SDI=y
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y
+CONFIG_FB_OMAP2=m
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+CONFIG_FB_OMAP2_NUM_FBS=3
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC_DPI=m
+# CONFIG_PANEL_TFP410 is not set
+# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set
+CONFIG_PANEL_SHARP_LS037V7DW01=m
+CONFIG_PANEL_NEC_NL8048HL11_01B=m
+# CONFIG_PANEL_PICODLP is not set
+CONFIG_PANEL_TAAL=m
+CONFIG_PANEL_TPO_TD043MTEA1=m
+CONFIG_PANEL_ACX565AKM=m
+# CONFIG_PANEL_N8X0 is not set
+# CONFIG_EXYNOS_VIDEO is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_L4F00242T03 is not set
+# CONFIG_LCD_LMS283GF05 is not set
+# CONFIG_LCD_LTV350QV is not set
+CONFIG_LCD_ILI9320=y
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+CONFIG_LCD_PLATFORM=y
+# CONFIG_LCD_S6E63M0 is not set
+# CONFIG_LCD_LD9040 is not set
+# CONFIG_LCD_AMS369FG06 is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=m
+CONFIG_BACKLIGHT_PWM=y
+# CONFIG_BACKLIGHT_ADP8860 is not set
+# CONFIG_BACKLIGHT_ADP8870 is not set
+CONFIG_BACKLIGHT_LM3630=m
+CONFIG_BACKLIGHT_LM3639=m
+# CONFIG_BACKLIGHT_LP855X is not set
+# CONFIG_BACKLIGHT_PANDORA is not set
+CONFIG_BACKLIGHT_TPS65217=y
+# CONFIG_BACKLIGHT_TLC59108 is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_FB_SSD1307 is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_COMPRESS_OFFLOAD=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_ALOOP is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_AM33XX_SOC=y
+# CONFIG_SND_DESIGNWARE_I2S is not set
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TLV320AIC3X=y
+# CONFIG_SND_SIMPLE_CARD is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+CONFIG_UHID=m
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+CONFIG_HID_LENOVO_TPKBD=m
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PRIMAX is not set
+CONFIG_HID_PS3REMOTE=m
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_WIIMOTE is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+CONFIG_HID_SENSOR_HUB=m
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB_ARCH_HAS_XHCI is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+# CONFIG_USB_MUSB_TUSB6010 is not set
+# CONFIG_USB_MUSB_OMAP2PLUS is not set
+# CONFIG_USB_MUSB_AM35X is not set
+CONFIG_USB_MUSB_DSPS=y
+CONFIG_MUSB_PIO_ONLY=y
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_RENESAS_USBHS is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_F81232=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_METRO=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
+CONFIG_USB_SERIAL_ZIO=m
+CONFIG_USB_SERIAL_ZTE=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_QT2=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
+# CONFIG_USB_SISUSBVGA is not set
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_YUREX=m
+CONFIG_USB_EZUSB_FX2=m
+
+#
+# USB Physical Layer drivers
+#
+CONFIG_OMAP_USB2=y
+CONFIG_USB_ISP1301=m
+# CONFIG_USB_RCAR_PHY is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+
+#
+# USB Peripheral Controller
+#
+# CONFIG_USB_FUSB300 is not set
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_MV_UDC is not set
+CONFIG_USB_GADGET_MUSB_HDRC=y
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_LIBCOMPOSITE=m
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_ETH_EEM is not set
+# CONFIG_USB_G_NCM is not set
+CONFIG_USB_GADGETFS=m
+# CONFIG_USB_FUNCTIONFS is not set
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+CONFIG_USB_CDC_COMPOSITE=m
+# CONFIG_USB_G_NOKIA is not set
+# CONFIG_USB_G_ACM_MS is not set
+# CONFIG_USB_G_MULTI is not set
+CONFIG_USB_G_HID=m
+# CONFIG_USB_G_DBGP is not set
+# CONFIG_USB_G_WEBCAM is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=m
+# CONFIG_USB_ULPI is not set
+CONFIG_TWL6030_USB=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SDHCI_PXAV3 is not set
+# CONFIG_MMC_SDHCI_PXAV2 is not set
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_LM3530 is not set
+CONFIG_LEDS_LM3642=m
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_PCA9633 is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_REGULATOR is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+# CONFIG_LEDS_RENESAS_TPU is not set
+# CONFIG_LEDS_TCA6507 is not set
+CONFIG_LEDS_LM355x=m
+# CONFIG_LEDS_OT200 is not set
+CONFIG_LEDS_BLINKM=m
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+CONFIG_LEDS_TRIGGER_TRANSIENT=y
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+CONFIG_RTC_DRV_DS2404=m
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_OMAP is not set
+CONFIG_RTC_DRV_SNVS=m
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+# CONFIG_DW_DMAC is not set
+# CONFIG_TIMB_DMA is not set
+CONFIG_TI_EDMA=y
+# CONFIG_DMA_OMAP is not set
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+
+#
+# DMA Clients
+#
+# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=y
+CONFIG_UIO_PDRV=y
+CONFIG_UIO_PDRV_GENIRQ=y
+# CONFIG_UIO_DMEM_GENIRQ is not set
+CONFIG_VIRTIO=m
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_BALLOON is not set
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_DEBUG is not set
+CONFIG_HWSPINLOCK=m
+
+#
+# Hardware Spinlock drivers
+#
+CONFIG_HWSPINLOCK_OMAP=m
+CONFIG_CLKSRC_MMIO=y
+CONFIG_IOMMU_SUPPORT=y
+CONFIG_OF_IOMMU=y
+# CONFIG_OMAP_IOMMU is not set
+
+#
+# Remoteproc drivers (EXPERIMENTAL)
+#
+CONFIG_REMOTEPROC=m
+CONFIG_STE_MODEM_RPROC=m
+
+#
+# Rpmsg drivers (EXPERIMENTAL)
+#
+# CONFIG_VIRT_DRIVERS is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+CONFIG_IIO=y
+CONFIG_IIO_BUFFER=y
+# CONFIG_IIO_BUFFER_CB is not set
+CONFIG_IIO_KFIFO_BUF=m
+CONFIG_IIO_TRIGGERED_BUFFER=m
+CONFIG_IIO_TRIGGER=y
+CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
+
+#
+# Accelerometers
+#
+CONFIG_HID_SENSOR_ACCEL_3D=m
+
+#
+# Analog to digital converters
+#
+CONFIG_AD_SIGMA_DELTA=m
+CONFIG_AD7266=m
+# CONFIG_AD7298 is not set
+CONFIG_AD7791=m
+# CONFIG_AD7793 is not set
+CONFIG_AD7476=m
+# CONFIG_AD7887 is not set
+# CONFIG_MAX1363 is not set
+# CONFIG_TI_ADC081C is not set
+CONFIG_TI_AM335X_ADC=y
+
+#
+# Amplifiers
+#
+# CONFIG_AD8366 is not set
+
+#
+# Hid Sensor IIO Common
+#
+CONFIG_HID_SENSOR_IIO_COMMON=m
+CONFIG_HID_SENSOR_IIO_TRIGGER=m
+# CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS is not set
+
+#
+# Digital to analog converters
+#
+CONFIG_AD5064=m
+CONFIG_AD5360=m
+CONFIG_AD5380=m
+CONFIG_AD5421=m
+CONFIG_AD5624R_SPI=m
+CONFIG_AD5446=m
+# CONFIG_AD5449 is not set
+CONFIG_AD5504=m
+CONFIG_AD5755=m
+CONFIG_AD5764=m
+CONFIG_AD5791=m
+CONFIG_AD5686=m
+CONFIG_MAX517=m
+CONFIG_MCP4725=m
+
+#
+# Frequency Synthesizers DDS/PLL
+#
+
+#
+# Clock Generator/Distribution
+#
+CONFIG_AD9523=m
+
+#
+# Phase-Locked Loop (PLL) frequency synthesizers
+#
+CONFIG_ADF4350=m
+
+#
+# Digital gyroscope sensors
+#
+# CONFIG_ADIS16136 is not set
+CONFIG_HID_SENSOR_GYRO_3D=m
+
+#
+# Inertial measurement units
+#
+# CONFIG_ADIS16480 is not set
+
+#
+# Light sensors
+#
+CONFIG_ADJD_S311=m
+CONFIG_VCNL4000=m
+CONFIG_HID_SENSOR_ALS=m
+
+#
+# Magnetometer sensors
+#
+CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
+CONFIG_PWM=y
+CONFIG_PWM_TIECAP=y
+CONFIG_PWM_TIEHRPWM=y
+CONFIG_PWM_TIPWMSS=y
+# CONFIG_PWM_TWL is not set
+# CONFIG_PWM_TWL_LED is not set
+# CONFIG_EHRPWM_TEST is not set
+# CONFIG_IPACK_BUS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set
+CONFIG_NILFS2_FS=m
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=m
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_STAT_FS=y
+CONFIG_F2FS_FS_XATTR=y
+CONFIG_F2FS_FS_POSIX_ACL=y
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_SUNRPC_SWAP=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=60
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_REDUCED=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_RCU_CPU_STALL_INFO is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_LKDTM is not set
+CONFIG_NOTIFIER_ERROR_INJECTION=m
+# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set
+CONFIG_PM_NOTIFIER_ERROR_INJECT=m
+# CONFIG_OF_RECONFIG_NOTIFIER_ERROR_INJECT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACE_CLOCK=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_EVENT_POWER_TRACING_DEPRECATED=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_KPROBE_EVENT=y
+CONFIG_PROBE_EVENTS=y
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_LL_UART_NONE=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_SEMIHOSTING is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+CONFIG_EARLY_PRINTK=y
+# CONFIG_ARM_KPROBES_TEST is not set
+# CONFIG_PID_IN_CONTEXTIDR is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_SMACK is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_SECURITY_YAMA is not set
+# CONFIG_IMA is not set
+# CONFIG_EVM is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_PCRYPT=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA1_ARM is not set
+CONFIG_CRYPTO_SHA256=m
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_AES_ARM=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_OMAP_SHAM is not set
+# CONFIG_CRYPTO_DEV_OMAP_AES is not set
+CONFIG_ASYMMETRIC_KEY_TYPE=m
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
+CONFIG_PUBLIC_KEY_ALGO_RSA=m
+CONFIG_X509_CERTIFICATE_PARSER=m
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_PERCPU_RWSEM=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CPU_RMAP=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_AVERAGE=y
+CONFIG_CLZ_TAB=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+CONFIG_MPILIB=m
+CONFIG_OID_REGISTRY=m
diff --git a/drivers/Kconfig b/drivers/Kconfig
index f5fb072..0e8852a 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -158,4 +158,6 @@ source "drivers/irqchip/Kconfig"
 
 source "drivers/ipack/Kconfig"
 
+source "drivers/rstctl/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 7863b9f..8c50114 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -11,6 +11,8 @@ obj-y				+= bus/
 # GPIO must come after pinctrl as gpios may need to mux pins etc
 obj-y				+= pinctrl/
 obj-y				+= gpio/
+# similarly rstctl must come very early
+obj-y				+= rstctl/
 obj-y				+= pwm/
 obj-$(CONFIG_PCI)		+= pci/
 obj-$(CONFIG_PARISC)		+= parisc/
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index c0b8df3..dab9552 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -270,6 +270,80 @@ int platform_device_add_data(struct platform_device *pdev, const void *data,
 }
 EXPORT_SYMBOL_GPL(platform_device_add_data);
 
+static struct resource *platform_device_parent_resource(
+		struct platform_device *pdev, struct resource *r)
+{
+	unsigned long type;
+
+	if (r->parent)
+		return r->parent;
+
+	type = resource_type(r);
+	switch (type) {
+		case IORESOURCE_MEM:
+			return &iomem_resource;
+		case IORESOURCE_IO:
+			return &ioport_resource;
+		/* TODO: What about the other resources? */
+		default:
+			break;
+	}
+	pr_debug("%s: no parent for resource %p type 0x%lx\n",
+			dev_name(&pdev->dev), r, resource_type(r));
+	return NULL;
+}
+
+int platform_device_unlink_resources(struct platform_device *pdev)
+{
+	struct resource *r;
+	int i;
+
+	for (i = pdev->num_resources - 1; i >= 0; i--) {
+		r = &pdev->resource[i];
+		if (r->parent == NULL)
+			continue;
+		release_resource(r);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(platform_device_unlink_resources);
+
+int platform_device_link_resources(struct platform_device *pdev)
+{
+	int i;
+	struct resource *p, *r;
+
+	for (i = 0; i < pdev->num_resources; i++) {
+		r = &pdev->resource[i];
+
+		if (r->name == NULL)
+			r->name = dev_name(&pdev->dev);
+
+		/* already linked */
+		if (r->parent != NULL)
+			continue;
+
+		p = platform_device_parent_resource(pdev, r);
+		if (p && insert_resource(p, r)) {
+			pr_err("%s: failed to claim resource %d\n",
+			       dev_name(&pdev->dev), i);
+			goto fail;
+		}
+	}
+
+	return 0;
+
+fail:
+	while (--i >= 0) {
+		r = &pdev->resource[i];
+		if (r->parent == NULL)
+			continue;
+		release_resource(r);
+	}
+	return -EBUSY;
+}
+EXPORT_SYMBOL_GPL(platform_device_link_resources);
+
 /**
  * platform_device_add - add a platform device to device hierarchy
  * @pdev: platform device we're adding
@@ -279,7 +353,7 @@ EXPORT_SYMBOL_GPL(platform_device_add_data);
  */
 int platform_device_add(struct platform_device *pdev)
 {
-	int i, ret;
+	int ret;
 
 	if (!pdev)
 		return -EINVAL;
@@ -311,28 +385,10 @@ int platform_device_add(struct platform_device *pdev)
 		break;
 	}
 
-	for (i = 0; i < pdev->num_resources; i++) {
-		struct resource *p, *r = &pdev->resource[i];
-
-		if (r->name == NULL)
-			r->name = dev_name(&pdev->dev);
-
-		p = r->parent;
-		if (!p) {
-			if (resource_type(r) == IORESOURCE_MEM)
-				p = &iomem_resource;
-			else if (resource_type(r) == IORESOURCE_IO)
-				p = &ioport_resource;
-		}
-
-		if (p && insert_resource(p, r)) {
-			printk(KERN_ERR
-			       "%s: failed to claim resource %d\n",
-			       dev_name(&pdev->dev), i);
-			ret = -EBUSY;
-			goto failed;
-		}
-	}
+	/* make sure the resources are linked properly */
+	ret = platform_device_link_resources(pdev);
+	if (ret != 0)
+		goto failed_res;
 
 	pr_debug("Registering platform device '%s'. Parent at %s\n",
 		 dev_name(&pdev->dev), dev_name(pdev->dev.parent));
@@ -341,20 +397,14 @@ int platform_device_add(struct platform_device *pdev)
 	if (ret == 0)
 		return ret;
 
- failed:
+	platform_device_unlink_resources(pdev);
+
+ failed_res:
 	if (pdev->id_auto) {
 		ida_simple_remove(&platform_devid_ida, pdev->id);
 		pdev->id = PLATFORM_DEVID_AUTO;
 	}
 
-	while (--i >= 0) {
-		struct resource *r = &pdev->resource[i];
-		unsigned long type = resource_type(r);
-
-		if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
-			release_resource(r);
-	}
-
  err_out:
 	return ret;
 }
@@ -370,8 +420,6 @@ EXPORT_SYMBOL_GPL(platform_device_add);
  */
 void platform_device_del(struct platform_device *pdev)
 {
-	int i;
-
 	if (pdev) {
 		device_del(&pdev->dev);
 
@@ -380,13 +428,7 @@ void platform_device_del(struct platform_device *pdev)
 			pdev->id = PLATFORM_DEVID_AUTO;
 		}
 
-		for (i = 0; i < pdev->num_resources; i++) {
-			struct resource *r = &pdev->resource[i];
-			unsigned long type = resource_type(r);
-
-			if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
-				release_resource(r);
-		}
+		platform_device_unlink_resources(pdev);
 	}
 }
 EXPORT_SYMBOL_GPL(platform_device_del);
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index a9204c6..ee648dc 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -32,6 +32,11 @@
 #define div_mask(d)	((1 << (d->width)) - 1)
 #define is_power_of_two(i)	!(i & ~i)
 
+static unsigned int _get_mindiv(struct clk_divider *divider)
+{
+	return divider->min_div;
+}
+
 static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
 {
 	unsigned int maxdiv = 0;
@@ -148,17 +153,18 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 {
 	struct clk_divider *divider = to_clk_divider(hw);
 	int i, bestdiv = 0;
-	unsigned long parent_rate, best = 0, now, maxdiv;
+	unsigned long parent_rate, best = 0, now, maxdiv, mindiv;
 
 	if (!rate)
 		rate = 1;
 
 	maxdiv = _get_maxdiv(divider);
+	mindiv = _get_mindiv(divider);
 
 	if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
 		parent_rate = *best_parent_rate;
 		bestdiv = DIV_ROUND_UP(parent_rate, rate);
-		bestdiv = bestdiv == 0 ? 1 : bestdiv;
+		bestdiv = bestdiv == 0 ? mindiv : bestdiv;
 		bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
 		return bestdiv;
 	}
@@ -169,7 +175,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
 	 */
 	maxdiv = min(ULONG_MAX / rate, maxdiv);
 
-	for (i = 1; i <= maxdiv; i++) {
+	for (i = mindiv; i <= maxdiv; i++) {
 		if (!_is_valid_div(divider, i))
 			continue;
 		parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
@@ -236,7 +242,7 @@ EXPORT_SYMBOL_GPL(clk_divider_ops);
 
 static struct clk *_register_divider(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
-		void __iomem *reg, u8 shift, u8 width,
+		void __iomem *reg, u8 shift, u8 width, u8 min_div,
 		u8 clk_divider_flags, const struct clk_div_table *table,
 		spinlock_t *lock)
 {
@@ -244,6 +250,11 @@ static struct clk *_register_divider(struct device *dev, const char *name,
 	struct clk *clk;
 	struct clk_init_data init;
 
+	if (!min_div) {
+		pr_err("%s: minimum divider cannot be zero\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
 	/* allocate the divider */
 	div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
 	if (!div) {
@@ -261,6 +272,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
 	div->reg = reg;
 	div->shift = shift;
 	div->width = width;
+	div->min_div = min_div;
 	div->flags = clk_divider_flags;
 	div->lock = lock;
 	div->hw.init = &init;
@@ -276,6 +288,29 @@ static struct clk *_register_divider(struct device *dev, const char *name,
 }
 
 /**
+ * clk_register_min_divider - register a divider clock having minimum divider
+ * constraints with clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @min_div: minimum allowable divider
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @lock: shared register lock for this clock
+ */
+struct clk *clk_register_min_divider(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width, u8 min_div,
+		u8 clk_divider_flags, spinlock_t *lock)
+{
+	return _register_divider(dev, name, parent_name, flags, reg, shift,
+			width, min_div, clk_divider_flags, NULL, lock);
+}
+
+/**
  * clk_register_divider - register a divider clock with the clock framework
  * @dev: device registering this clock
  * @name: name of this clock
@@ -293,7 +328,8 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
 		u8 clk_divider_flags, spinlock_t *lock)
 {
 	return _register_divider(dev, name, parent_name, flags, reg, shift,
-			width, clk_divider_flags, NULL, lock);
+			width, CLK_DIVIDER_MIN_DIV_DEFAULT, clk_divider_flags,
+			NULL, lock);
 }
 
 /**
@@ -317,5 +353,6 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
 		spinlock_t *lock)
 {
 	return _register_divider(dev, name, parent_name, flags, reg, shift,
-			width, clk_divider_flags, table, lock);
+			width, CLK_DIVIDER_MIN_DIV_DEFAULT, clk_divider_flags,
+			table, lock);
 }
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 251e45d..8cb8b08 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1077,7 +1077,7 @@ out:
 	__clk_recalc_rates(clk, POST_RATE_CHANGE);
 }
 
-static int __clk_set_parent(struct clk *clk, struct clk *parent)
+int __clk_set_parent(struct clk *clk, struct clk *parent)
 {
 	struct clk *old_parent;
 	unsigned long flags;
@@ -1136,6 +1136,7 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent)
 out:
 	return ret;
 }
+EXPORT_SYMBOL_GPL(__clk_set_parent);
 
 /**
  * clk_set_parent - switch the parent of a mux clk
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index e66e8ee..6aa425f 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -5,6 +5,7 @@
  *
  * Copyright (c) 2010 Nokia Corporation
  * Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
+ * Copyright (c) 2011 Texas Instruments Incorporated
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as published
@@ -19,28 +20,39 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/omap-dma.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
 #include <linux/io.h>
 #include <linux/crypto.h>
 #include <linux/interrupt.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/aes.h>
 
-#include <linux/omap-dma.h>
+#define DST_MAXBURST			4
+#define DMA_MIN				(DST_MAXBURST * sizeof(u32))
 
 /* OMAP TRM gives bitfields as start:end, where start is the higher bit
    number. For example 7:0 */
 #define FLD_MASK(start, end)	(((1 << ((start) - (end) + 1)) - 1) << (end))
 #define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
 
-#define AES_REG_KEY(x)			(0x1C - ((x ^ 0x01) * 0x04))
-#define AES_REG_IV(x)			(0x20 + ((x) * 0x04))
+#define AES_REG_KEY(dd, x)		((dd)->pdata->key_ofs - \
+						((x ^ 0x01) * 0x04))
+#define AES_REG_IV(dd, x)		((dd)->pdata->iv_ofs + ((x) * 0x04))
 
-#define AES_REG_CTRL			0x30
-#define AES_REG_CTRL_CTR_WIDTH		(1 << 7)
+#define AES_REG_CTRL(dd)		((dd)->pdata->ctrl_ofs)
+#define AES_REG_CTRL_CTR_WIDTH_MASK	(3 << 7)
+#define AES_REG_CTRL_CTR_WIDTH_32		(0 << 7)
+#define AES_REG_CTRL_CTR_WIDTH_64		(1 << 7)
+#define AES_REG_CTRL_CTR_WIDTH_96		(2 << 7)
+#define AES_REG_CTRL_CTR_WIDTH_128		(3 << 7)
 #define AES_REG_CTRL_CTR		(1 << 6)
 #define AES_REG_CTRL_CBC		(1 << 5)
 #define AES_REG_CTRL_KEY_SIZE		(3 << 3)
@@ -48,14 +60,11 @@
 #define AES_REG_CTRL_INPUT_READY	(1 << 1)
 #define AES_REG_CTRL_OUTPUT_READY	(1 << 0)
 
-#define AES_REG_DATA			0x34
-#define AES_REG_DATA_N(x)		(0x34 + ((x) * 0x04))
+#define AES_REG_DATA_N(dd, x)		((dd)->pdata->data_ofs + ((x) * 0x04))
 
-#define AES_REG_REV			0x44
-#define AES_REG_REV_MAJOR		0xF0
-#define AES_REG_REV_MINOR		0x0F
+#define AES_REG_REV(dd)			((dd)->pdata->rev_ofs)
 
-#define AES_REG_MASK			0x48
+#define AES_REG_MASK(dd)		((dd)->pdata->mask_ofs)
 #define AES_REG_MASK_SIDLE		(1 << 6)
 #define AES_REG_MASK_START		(1 << 5)
 #define AES_REG_MASK_DMA_OUT_EN		(1 << 3)
@@ -63,8 +72,7 @@
 #define AES_REG_MASK_SOFTRESET		(1 << 1)
 #define AES_REG_AUTOIDLE		(1 << 0)
 
-#define AES_REG_SYSSTATUS		0x4C
-#define AES_REG_SYSSTATUS_RESETDONE	(1 << 0)
+#define AES_REG_LENGTH_N(x)		(0x54 + ((x) * 0x04))
 
 #define DEFAULT_TIMEOUT		(5*HZ)
 
@@ -72,6 +80,7 @@
 #define FLAGS_ENCRYPT		BIT(0)
 #define FLAGS_CBC		BIT(1)
 #define FLAGS_GIV		BIT(2)
+#define FLAGS_CTR		BIT(3)
 
 #define FLAGS_INIT		BIT(4)
 #define FLAGS_FAST		BIT(5)
@@ -92,11 +101,39 @@ struct omap_aes_reqctx {
 #define OMAP_AES_QUEUE_LENGTH	1
 #define OMAP_AES_CACHE_SIZE	0
 
+struct omap_aes_algs_info {
+	struct crypto_alg	*algs_list;
+	unsigned int		size;
+	unsigned int		registered;
+};
+
+struct omap_aes_pdata {
+	struct omap_aes_algs_info	*algs_info;
+	unsigned int	algs_info_size;
+
+	void		(*trigger)(struct omap_aes_dev *dd, int length);
+
+	u32		key_ofs;
+	u32		iv_ofs;
+	u32		ctrl_ofs;
+	u32		data_ofs;
+	u32		rev_ofs;
+	u32		mask_ofs;
+
+	u32		dma_enable_in;
+	u32		dma_enable_out;
+	u32		dma_start;
+
+	u32		major_mask;
+	u32		major_shift;
+	u32		minor_mask;
+	u32		minor_shift;
+};
+
 struct omap_aes_dev {
 	struct list_head	list;
 	unsigned long		phys_base;
 	void __iomem		*io_base;
-	struct clk		*iclk;
 	struct omap_aes_ctx	*ctx;
 	struct device		*dev;
 	unsigned long		flags;
@@ -111,20 +148,24 @@ struct omap_aes_dev {
 	struct ablkcipher_request	*req;
 	size_t				total;
 	struct scatterlist		*in_sg;
+	struct scatterlist		in_sgl;
 	size_t				in_offset;
 	struct scatterlist		*out_sg;
+	struct scatterlist		out_sgl;
 	size_t				out_offset;
 
 	size_t			buflen;
 	void			*buf_in;
 	size_t			dma_size;
 	int			dma_in;
-	int			dma_lch_in;
+	struct dma_chan		*dma_lch_in;
 	dma_addr_t		dma_addr_in;
 	void			*buf_out;
 	int			dma_out;
-	int			dma_lch_out;
+	struct dma_chan		*dma_lch_out;
 	dma_addr_t		dma_addr_out;
+
+	const struct omap_aes_pdata	*pdata;
 };
 
 /* keep registered devices data here */
@@ -160,19 +201,6 @@ static void omap_aes_write_n(struct omap_aes_dev *dd, u32 offset,
 		omap_aes_write(dd, offset, *value);
 }
 
-static int omap_aes_wait(struct omap_aes_dev *dd, u32 offset, u32 bit)
-{
-	unsigned long timeout = jiffies + DEFAULT_TIMEOUT;
-
-	while (!(omap_aes_read(dd, offset) & bit)) {
-		if (time_is_before_jiffies(timeout)) {
-			dev_err(dd->dev, "omap-aes timeout\n");
-			return -ETIMEDOUT;
-		}
-	}
-	return 0;
-}
-
 static int omap_aes_hw_init(struct omap_aes_dev *dd)
 {
 	/*
@@ -180,23 +208,9 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd)
 	 * It may be long delays between requests.
 	 * Device might go to off mode to save power.
 	 */
-	clk_enable(dd->iclk);
+	pm_runtime_get_sync(dd->dev);
 
 	if (!(dd->flags & FLAGS_INIT)) {
-		/* is it necessary to reset before every operation? */
-		omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET,
-					AES_REG_MASK_SOFTRESET);
-		/*
-		 * prevent OCP bus error (SRESP) in case an access to the module
-		 * is performed while the module is coming out of soft reset
-		 */
-		__asm__ __volatile__("nop");
-		__asm__ __volatile__("nop");
-
-		if (omap_aes_wait(dd, AES_REG_SYSSTATUS,
-				AES_REG_SYSSTATUS_RESETDONE))
-			return -ETIMEDOUT;
-
 		dd->flags |= FLAGS_INIT;
 		dd->err = 0;
 	}
@@ -208,59 +222,75 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
 {
 	unsigned int key32;
 	int i, err;
-	u32 val, mask;
+	u32 val, mask = 0;
 
 	err = omap_aes_hw_init(dd);
 	if (err)
 		return err;
 
-	val = 0;
-	if (dd->dma_lch_out >= 0)
-		val |= AES_REG_MASK_DMA_OUT_EN;
-	if (dd->dma_lch_in >= 0)
-		val |= AES_REG_MASK_DMA_IN_EN;
-
-	mask = AES_REG_MASK_DMA_IN_EN | AES_REG_MASK_DMA_OUT_EN;
-
-	omap_aes_write_mask(dd, AES_REG_MASK, val, mask);
-
 	key32 = dd->ctx->keylen / sizeof(u32);
 
 	/* it seems a key should always be set even if it has not changed */
 	for (i = 0; i < key32; i++) {
-		omap_aes_write(dd, AES_REG_KEY(i),
+		omap_aes_write(dd, AES_REG_KEY(dd, i),
 			__le32_to_cpu(dd->ctx->key[i]));
 	}
 
-	if ((dd->flags & FLAGS_CBC) && dd->req->info)
-		omap_aes_write_n(dd, AES_REG_IV(0), dd->req->info, 4);
+	if ((dd->flags & (FLAGS_CBC | FLAGS_CTR)) && dd->req->info)
+		omap_aes_write_n(dd, AES_REG_IV(dd, 0), dd->req->info, 4);
 
 	val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
 	if (dd->flags & FLAGS_CBC)
 		val |= AES_REG_CTRL_CBC;
+	if (dd->flags & FLAGS_CTR) {
+		val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_32;
+		mask = AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_MASK;
+	}
 	if (dd->flags & FLAGS_ENCRYPT)
 		val |= AES_REG_CTRL_DIRECTION;
 
-	mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
+	mask |= AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
 			AES_REG_CTRL_KEY_SIZE;
 
-	omap_aes_write_mask(dd, AES_REG_CTRL, val, mask);
+	omap_aes_write_mask(dd, AES_REG_CTRL(dd), val, mask);
 
-	/* IN */
-	omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
-				 dd->phys_base + AES_REG_DATA, 0, 4);
+	return 0;
+}
 
-	omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
-	omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
+static void omap_aes_dma_trigger_omap2(struct omap_aes_dev *dd, int length)
+{
+	u32 mask, val;
 
-	/* OUT */
-	omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT,
-				dd->phys_base + AES_REG_DATA, 0, 4);
+	val = dd->pdata->dma_start;
 
-	omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
-	omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
+	if (dd->dma_lch_out != NULL)
+		val |= dd->pdata->dma_enable_out;
+	if (dd->dma_lch_in != NULL)
+		val |= dd->pdata->dma_enable_in;
+
+	mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in |
+	       dd->pdata->dma_start;
+
+	omap_aes_write_mask(dd, AES_REG_MASK(dd), val, mask);
 
-	return 0;
+}
+
+static void omap_aes_dma_trigger_omap4(struct omap_aes_dev *dd, int length)
+{
+	omap_aes_write(dd, AES_REG_LENGTH_N(0), length);
+	omap_aes_write(dd, AES_REG_LENGTH_N(1), 0);
+
+	omap_aes_dma_trigger_omap2(dd, length);
+}
+
+static void omap_aes_dma_stop(struct omap_aes_dev *dd)
+{
+	u32 mask;
+
+	mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in |
+	       dd->pdata->dma_start;
+
+	omap_aes_write_mask(dd, AES_REG_MASK(dd), 0, mask);
 }
 
 static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
@@ -284,18 +314,10 @@ static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
 	return dd;
 }
 
-static void omap_aes_dma_callback(int lch, u16 ch_status, void *data)
+static void omap_aes_dma_out_callback(void *data)
 {
 	struct omap_aes_dev *dd = data;
 
-	if (ch_status != OMAP_DMA_BLOCK_IRQ) {
-		pr_err("omap-aes DMA error status: 0x%hx\n", ch_status);
-		dd->err = -EIO;
-		dd->flags &= ~FLAGS_INIT; /* request to re-initialize */
-	} else if (lch == dd->dma_lch_in) {
-		return;
-	}
-
 	/* dma_lch_out - completed */
 	tasklet_schedule(&dd->done_task);
 }
@@ -303,9 +325,10 @@ static void omap_aes_dma_callback(int lch, u16 ch_status, void *data)
 static int omap_aes_dma_init(struct omap_aes_dev *dd)
 {
 	int err = -ENOMEM;
+	dma_cap_mask_t mask;
 
-	dd->dma_lch_out = -1;
-	dd->dma_lch_in = -1;
+	dd->dma_lch_out = NULL;
+	dd->dma_lch_in = NULL;
 
 	dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE);
 	dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE);
@@ -334,23 +357,31 @@ static int omap_aes_dma_init(struct omap_aes_dev *dd)
 		goto err_map_out;
 	}
 
-	err = omap_request_dma(dd->dma_in, "omap-aes-rx",
-			       omap_aes_dma_callback, dd, &dd->dma_lch_in);
-	if (err) {
-		dev_err(dd->dev, "Unable to request DMA channel\n");
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	dd->dma_lch_in = dma_request_slave_channel_compat(mask,
+							  omap_dma_filter_fn,
+							  &dd->dma_in,
+							  dd->dev, "rx");
+	if (!dd->dma_lch_in) {
+		dev_err(dd->dev, "Unable to request in DMA channel\n");
 		goto err_dma_in;
 	}
-	err = omap_request_dma(dd->dma_out, "omap-aes-tx",
-			       omap_aes_dma_callback, dd, &dd->dma_lch_out);
-	if (err) {
-		dev_err(dd->dev, "Unable to request DMA channel\n");
+
+	dd->dma_lch_out = dma_request_slave_channel_compat(mask,
+							   omap_dma_filter_fn,
+							   &dd->dma_out,
+							   dd->dev, "tx");
+	if (!dd->dma_lch_out) {
+		dev_err(dd->dev, "Unable to request out DMA channel\n");
 		goto err_dma_out;
 	}
 
 	return 0;
 
 err_dma_out:
-	omap_free_dma(dd->dma_lch_in);
+	dma_release_channel(dd->dma_lch_in);
 err_dma_in:
 	dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
 			 DMA_FROM_DEVICE);
@@ -367,8 +398,8 @@ err_alloc:
 
 static void omap_aes_dma_cleanup(struct omap_aes_dev *dd)
 {
-	omap_free_dma(dd->dma_lch_out);
-	omap_free_dma(dd->dma_lch_in);
+	dma_release_channel(dd->dma_lch_out);
+	dma_release_channel(dd->dma_lch_in);
 	dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
 			 DMA_FROM_DEVICE);
 	dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, DMA_TO_DEVICE);
@@ -426,12 +457,15 @@ static int sg_copy(struct scatterlist **sg, size_t *offset, void *buf,
 	return off;
 }
 
-static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
-			       dma_addr_t dma_addr_out, int length)
+static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
+		struct scatterlist *in_sg, struct scatterlist *out_sg)
 {
 	struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
 	struct omap_aes_dev *dd = ctx->dd;
-	int len32;
+	struct dma_async_tx_descriptor *tx_in, *tx_out;
+	struct dma_slave_config cfg;
+	dma_addr_t dma_addr_in = sg_dma_address(in_sg);
+	int ret, length = sg_dma_len(in_sg);
 
 	pr_debug("len: %d\n", length);
 
@@ -441,30 +475,61 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
 		dma_sync_single_for_device(dd->dev, dma_addr_in, length,
 					   DMA_TO_DEVICE);
 
-	len32 = DIV_ROUND_UP(length, sizeof(u32));
+	memset(&cfg, 0, sizeof(cfg));
+
+	cfg.src_addr = dd->phys_base + AES_REG_DATA_N(dd, 0);
+	cfg.dst_addr = dd->phys_base + AES_REG_DATA_N(dd, 0);
+	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.src_maxburst = DST_MAXBURST;
+	cfg.dst_maxburst = DST_MAXBURST;
 
 	/* IN */
-	omap_set_dma_transfer_params(dd->dma_lch_in, OMAP_DMA_DATA_TYPE_S32,
-				     len32, 1, OMAP_DMA_SYNC_PACKET, dd->dma_in,
-					OMAP_DMA_DST_SYNC);
+	ret = dmaengine_slave_config(dd->dma_lch_in, &cfg);
+	if (ret) {
+		dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n",
+			ret);
+		return ret;
+	}
+
+	tx_in = dmaengine_prep_slave_sg(dd->dma_lch_in, in_sg, 1,
+					DMA_MEM_TO_DEV,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!tx_in) {
+		dev_err(dd->dev, "IN prep_slave_sg() failed\n");
+		return -EINVAL;
+	}
 
-	omap_set_dma_src_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_POST_INC,
-				dma_addr_in, 0, 0);
+	/* No callback necessary */
+	tx_in->callback_param = dd;
 
 	/* OUT */
-	omap_set_dma_transfer_params(dd->dma_lch_out, OMAP_DMA_DATA_TYPE_S32,
-				     len32, 1, OMAP_DMA_SYNC_PACKET,
-					dd->dma_out, OMAP_DMA_SRC_SYNC);
+	ret = dmaengine_slave_config(dd->dma_lch_out, &cfg);
+	if (ret) {
+		dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n",
+			ret);
+		return ret;
+	}
+
+	tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg, 1,
+					DMA_DEV_TO_MEM,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!tx_out) {
+		dev_err(dd->dev, "OUT prep_slave_sg() failed\n");
+		return -EINVAL;
+	}
 
-	omap_set_dma_dest_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_POST_INC,
-				 dma_addr_out, 0, 0);
+	tx_out->callback = omap_aes_dma_out_callback;
+	tx_out->callback_param = dd;
 
-	omap_start_dma(dd->dma_lch_in);
-	omap_start_dma(dd->dma_lch_out);
+	dmaengine_submit(tx_in);
+	dmaengine_submit(tx_out);
 
-	/* start DMA or disable idle mode */
-	omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START,
-			    AES_REG_MASK_START);
+	dma_async_issue_pending(dd->dma_lch_in);
+	dma_async_issue_pending(dd->dma_lch_out);
+
+	/* start DMA */
+	dd->pdata->trigger(dd, length);
 
 	return 0;
 }
@@ -476,6 +541,8 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
 	int err, fast = 0, in, out;
 	size_t count;
 	dma_addr_t addr_in, addr_out;
+	struct scatterlist *in_sg, *out_sg;
+	int len32;
 
 	pr_debug("total: %d\n", dd->total);
 
@@ -514,6 +581,9 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
 		addr_in = sg_dma_address(dd->in_sg);
 		addr_out = sg_dma_address(dd->out_sg);
 
+		in_sg = dd->in_sg;
+		out_sg = dd->out_sg;
+
 		dd->flags |= FLAGS_FAST;
 
 	} else {
@@ -521,6 +591,27 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
 		count = sg_copy(&dd->in_sg, &dd->in_offset, dd->buf_in,
 				 dd->buflen, dd->total, 0);
 
+		len32 = DIV_ROUND_UP(count, DMA_MIN) * DMA_MIN;
+
+		/*
+		 * The data going into the AES module has been copied
+		 * to a local buffer and the data coming out will go
+		 * into a local buffer so set up local SG entries for
+		 * both.
+		 */
+		sg_init_table(&dd->in_sgl, 1);
+		dd->in_sgl.offset = dd->in_offset;
+		sg_dma_len(&dd->in_sgl) = len32;
+		sg_dma_address(&dd->in_sgl) = dd->dma_addr_in;
+
+		sg_init_table(&dd->out_sgl, 1);
+		dd->out_sgl.offset = dd->out_offset;
+		sg_dma_len(&dd->out_sgl) = len32;
+		sg_dma_address(&dd->out_sgl) = dd->dma_addr_out;
+
+		in_sg = &dd->in_sgl;
+		out_sg = &dd->out_sgl;
+
 		addr_in = dd->dma_addr_in;
 		addr_out = dd->dma_addr_out;
 
@@ -530,7 +621,7 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
 
 	dd->total -= count;
 
-	err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count);
+	err = omap_aes_crypt_dma(tfm, in_sg, out_sg);
 	if (err) {
 		dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
 		dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
@@ -545,7 +636,7 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err)
 
 	pr_debug("err: %d\n", err);
 
-	clk_disable(dd->iclk);
+	pm_runtime_put_sync(dd->dev);
 	dd->flags &= ~FLAGS_BUSY;
 
 	req->base.complete(&req->base, err);
@@ -558,10 +649,10 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
 
 	pr_debug("total: %d\n", dd->total);
 
-	omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START);
+	omap_aes_dma_stop(dd);
 
-	omap_stop_dma(dd->dma_lch_in);
-	omap_stop_dma(dd->dma_lch_out);
+	dmaengine_terminate_all(dd->dma_lch_in);
+	dmaengine_terminate_all(dd->dma_lch_out);
 
 	if (dd->flags & FLAGS_FAST) {
 		dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
@@ -734,6 +825,16 @@ static int omap_aes_cbc_decrypt(struct ablkcipher_request *req)
 	return omap_aes_crypt(req, FLAGS_CBC);
 }
 
+static int omap_aes_ctr_encrypt(struct ablkcipher_request *req)
+{
+	return omap_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_CTR);
+}
+
+static int omap_aes_ctr_decrypt(struct ablkcipher_request *req)
+{
+	return omap_aes_crypt(req, FLAGS_CTR);
+}
+
 static int omap_aes_cra_init(struct crypto_tfm *tfm)
 {
 	pr_debug("enter\n");
@@ -750,7 +851,7 @@ static void omap_aes_cra_exit(struct crypto_tfm *tfm)
 
 /* ********************** ALGS ************************************ */
 
-static struct crypto_alg algs[] = {
+static struct crypto_alg algs_ecb_cbc[] = {
 {
 	.cra_name		= "ecb(aes)",
 	.cra_driver_name	= "ecb-aes-omap",
@@ -798,11 +899,213 @@ static struct crypto_alg algs[] = {
 }
 };
 
+static struct crypto_alg algs_ctr[] = {
+{
+	.cra_name		= "ctr(aes)",
+	.cra_driver_name	= "ctr-aes-omap",
+	.cra_priority		= 100,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
+				  CRYPTO_ALG_KERN_DRIVER_ONLY |
+				  CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct omap_aes_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= omap_aes_cra_init,
+	.cra_exit		= omap_aes_cra_exit,
+	.cra_u.ablkcipher = {
+		.min_keysize	= AES_MIN_KEY_SIZE,
+		.max_keysize	= AES_MAX_KEY_SIZE,
+		.geniv		= "eseqiv",
+		.ivsize		= AES_BLOCK_SIZE,
+		.setkey		= omap_aes_setkey,
+		.encrypt	= omap_aes_ctr_encrypt,
+		.decrypt	= omap_aes_ctr_decrypt,
+	}
+} ,
+};
+
+static struct omap_aes_algs_info omap_aes_algs_info_ecb_cbc[] = {
+	{
+		.algs_list	= algs_ecb_cbc,
+		.size		= ARRAY_SIZE(algs_ecb_cbc),
+	},
+};
+
+static const struct omap_aes_pdata omap_aes_pdata_omap2 = {
+	.algs_info	= omap_aes_algs_info_ecb_cbc,
+	.algs_info_size	= ARRAY_SIZE(omap_aes_algs_info_ecb_cbc),
+	.trigger	= omap_aes_dma_trigger_omap2,
+	.key_ofs	= 0x1c,
+	.iv_ofs		= 0x20,
+	.ctrl_ofs	= 0x30,
+	.data_ofs	= 0x34,
+	.rev_ofs	= 0x44,
+	.mask_ofs	= 0x48,
+	.dma_enable_in	= BIT(2),
+	.dma_enable_out	= BIT(3),
+	.dma_start	= BIT(5),
+	.major_mask	= 0xf0,
+	.major_shift	= 4,
+	.minor_mask	= 0x0f,
+	.minor_shift	= 0,
+};
+
+#ifdef CONFIG_OF
+static struct omap_aes_algs_info omap_aes_algs_info_ecb_cbc_ctr[] = {
+	{
+		.algs_list	= algs_ecb_cbc,
+		.size		= ARRAY_SIZE(algs_ecb_cbc),
+	},
+	{
+		.algs_list	= algs_ctr,
+		.size		= ARRAY_SIZE(algs_ctr),
+	},
+};
+
+static const struct omap_aes_pdata omap_aes_pdata_omap3 = {
+	.algs_info	= omap_aes_algs_info_ecb_cbc_ctr,
+	.algs_info_size	= ARRAY_SIZE(omap_aes_algs_info_ecb_cbc_ctr),
+	.trigger	= omap_aes_dma_trigger_omap2,
+	.key_ofs	= 0x1c,
+	.iv_ofs		= 0x20,
+	.ctrl_ofs	= 0x30,
+	.data_ofs	= 0x34,
+	.rev_ofs	= 0x44,
+	.mask_ofs	= 0x48,
+	.dma_enable_in	= BIT(2),
+	.dma_enable_out	= BIT(3),
+	.dma_start	= BIT(5),
+	.major_mask	= 0xf0,
+	.major_shift	= 4,
+	.minor_mask	= 0x0f,
+	.minor_shift	= 0,
+};
+
+static const struct omap_aes_pdata omap_aes_pdata_omap4 = {
+	.algs_info	= omap_aes_algs_info_ecb_cbc_ctr,
+	.algs_info_size	= ARRAY_SIZE(omap_aes_algs_info_ecb_cbc_ctr),
+	.trigger	= omap_aes_dma_trigger_omap4,
+	.key_ofs	= 0x3c,
+	.iv_ofs		= 0x40,
+	.ctrl_ofs	= 0x50,
+	.data_ofs	= 0x60,
+	.rev_ofs	= 0x80,
+	.mask_ofs	= 0x84,
+	.dma_enable_in	= BIT(5),
+	.dma_enable_out	= BIT(6),
+	.major_mask	= 0x0700,
+	.major_shift	= 8,
+	.minor_mask	= 0x003f,
+	.minor_shift	= 0,
+};
+
+static const struct of_device_id omap_aes_of_match[] = {
+	{
+		.compatible	= "ti,omap2-aes",
+		.data		= &omap_aes_pdata_omap2,
+	},
+	{
+		.compatible	= "ti,omap3-aes",
+		.data		= &omap_aes_pdata_omap3,
+	},
+	{
+		.compatible	= "ti,omap4-aes",
+		.data		= &omap_aes_pdata_omap4,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, omap_aes_of_match);
+
+static int omap_aes_get_res_of(struct omap_aes_dev *dd,
+		struct device *dev, struct resource *res)
+{
+	struct device_node *node = dev->of_node;
+	const struct of_device_id *match;
+	int err = 0;
+
+	match = of_match_device(of_match_ptr(omap_aes_of_match), dev);
+	if (!match) {
+		dev_err(dev, "no compatible OF match\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	err = of_address_to_resource(node, 0, res);
+	if (err < 0) {
+		dev_err(dev, "can't translate OF node address\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	dd->dma_out = -1; /* Dummy value that's unused */
+	dd->dma_in = -1; /* Dummy value that's unused */
+
+	dd->pdata = match->data;
+
+err:
+	return err;
+}
+#else
+static const struct of_device_id omap_aes_of_match[] = {
+	{},
+};
+
+static int omap_aes_get_res_of(struct omap_aes_dev *dd,
+		struct device *dev, struct resource *res)
+{
+	return -EINVAL;
+}
+#endif
+
+static int omap_aes_get_res_pdev(struct omap_aes_dev *dd,
+		struct platform_device *pdev, struct resource *res)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *r;
+	int err = 0;
+
+	/* Get the base address */
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(dev, "no MEM resource info\n");
+		err = -ENODEV;
+		goto err;
+	}
+	memcpy(res, r, sizeof(*res));
+
+	/* Get the DMA out channel */
+	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!r) {
+		dev_err(dev, "no DMA out resource info\n");
+		err = -ENODEV;
+		goto err;
+	}
+	dd->dma_out = r->start;
+
+	/* Get the DMA in channel */
+	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	if (!r) {
+		dev_err(dev, "no DMA in resource info\n");
+		err = -ENODEV;
+		goto err;
+	}
+	dd->dma_in = r->start;
+
+	/* Only OMAP2/3 can be non-DT */
+	dd->pdata = &omap_aes_pdata_omap2;
+
+err:
+	return err;
+}
+
 static int omap_aes_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct omap_aes_dev *dd;
-	struct resource *res;
+	struct crypto_alg *algp;
+	struct resource res;
 	int err = -ENOMEM, i, j;
 	u32 reg;
 
@@ -817,49 +1120,31 @@ static int omap_aes_probe(struct platform_device *pdev)
 	spin_lock_init(&dd->lock);
 	crypto_init_queue(&dd->queue, OMAP_AES_QUEUE_LENGTH);
 
-	/* Get the base address */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "invalid resource type\n");
-		err = -ENODEV;
-		goto err_res;
-	}
-	dd->phys_base = res->start;
-
-	/* Get the DMA */
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!res)
-		dev_info(dev, "no DMA info\n");
-	else
-		dd->dma_out = res->start;
-
-	/* Get the DMA */
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!res)
-		dev_info(dev, "no DMA info\n");
-	else
-		dd->dma_in = res->start;
-
-	/* Initializing the clock */
-	dd->iclk = clk_get(dev, "ick");
-	if (IS_ERR(dd->iclk)) {
-		dev_err(dev, "clock intialization failed.\n");
-		err = PTR_ERR(dd->iclk);
+	err = (dev->of_node) ? omap_aes_get_res_of(dd, dev, &res) :
+			       omap_aes_get_res_pdev(dd, pdev, &res);
+	if (err)
 		goto err_res;
-	}
 
-	dd->io_base = ioremap(dd->phys_base, SZ_4K);
+	dd->io_base = devm_request_and_ioremap(dev, &res);
 	if (!dd->io_base) {
 		dev_err(dev, "can't ioremap\n");
 		err = -ENOMEM;
-		goto err_io;
+		goto err_res;
 	}
+	dd->phys_base = res.start;
+
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
+
+	omap_aes_dma_stop(dd);
+
+	reg = omap_aes_read(dd, AES_REG_REV(dd));
+
+	pm_runtime_put_sync(dev);
 
-	clk_enable(dd->iclk);
-	reg = omap_aes_read(dd, AES_REG_REV);
 	dev_info(dev, "OMAP AES hw accel rev: %u.%u\n",
-		 (reg & AES_REG_REV_MAJOR) >> 4, reg & AES_REG_REV_MINOR);
-	clk_disable(dd->iclk);
+		 (reg & dd->pdata->major_mask) >> dd->pdata->major_shift,
+		 (reg & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
 
 	tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd);
 	tasklet_init(&dd->queue_task, omap_aes_queue_task, (unsigned long)dd);
@@ -873,26 +1158,32 @@ static int omap_aes_probe(struct platform_device *pdev)
 	list_add_tail(&dd->list, &dev_list);
 	spin_unlock(&list_lock);
 
-	for (i = 0; i < ARRAY_SIZE(algs); i++) {
-		pr_debug("i: %d\n", i);
-		err = crypto_register_alg(&algs[i]);
-		if (err)
-			goto err_algs;
-	}
+	for (i = 0; i < dd->pdata->algs_info_size; i++) {
+		for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
+			algp = &dd->pdata->algs_info[i].algs_list[j];
+
+			pr_debug("reg alg: %s\n", algp->cra_name);
+			INIT_LIST_HEAD(&algp->cra_list);
+
+			err = crypto_register_alg(algp);
+			if (err)
+				goto err_algs;
 
-	pr_info("probe() done\n");
+			dd->pdata->algs_info[i].registered++;
+		}
+	}
 
 	return 0;
 err_algs:
-	for (j = 0; j < i; j++)
-		crypto_unregister_alg(&algs[j]);
+	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
+		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
+			crypto_unregister_alg(
+					&dd->pdata->algs_info[i].algs_list[j]);
 	omap_aes_dma_cleanup(dd);
 err_dma:
 	tasklet_kill(&dd->done_task);
 	tasklet_kill(&dd->queue_task);
-	iounmap(dd->io_base);
-err_io:
-	clk_put(dd->iclk);
+	pm_runtime_disable(dev);
 err_res:
 	kfree(dd);
 	dd = NULL;
@@ -904,7 +1195,7 @@ err_data:
 static int omap_aes_remove(struct platform_device *pdev)
 {
 	struct omap_aes_dev *dd = platform_get_drvdata(pdev);
-	int i;
+	int i, j;
 
 	if (!dd)
 		return -ENODEV;
@@ -913,33 +1204,52 @@ static int omap_aes_remove(struct platform_device *pdev)
 	list_del(&dd->list);
 	spin_unlock(&list_lock);
 
-	for (i = 0; i < ARRAY_SIZE(algs); i++)
-		crypto_unregister_alg(&algs[i]);
+	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
+		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
+			crypto_unregister_alg(
+					&dd->pdata->algs_info[i].algs_list[j]);
 
 	tasklet_kill(&dd->done_task);
 	tasklet_kill(&dd->queue_task);
 	omap_aes_dma_cleanup(dd);
-	iounmap(dd->io_base);
-	clk_put(dd->iclk);
+	pm_runtime_disable(dd->dev);
 	kfree(dd);
 	dd = NULL;
 
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int omap_aes_suspend(struct device *dev)
+{
+	pm_runtime_put_sync(dev);
+	return 0;
+}
+
+static int omap_aes_resume(struct device *dev)
+{
+	pm_runtime_get_sync(dev);
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops omap_aes_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(omap_aes_suspend, omap_aes_resume)
+};
+
 static struct platform_driver omap_aes_driver = {
 	.probe	= omap_aes_probe,
 	.remove	= omap_aes_remove,
 	.driver	= {
 		.name	= "omap-aes",
 		.owner	= THIS_MODULE,
+		.pm	= &omap_aes_pm_ops,
+		.of_match_table	= omap_aes_of_match,
 	},
 };
 
 static int __init omap_aes_mod_init(void)
 {
-	pr_info("loading %s driver\n", "omap-aes");
-
 	return  platform_driver_register(&omap_aes_driver);
 }
 
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 90d34ad..696a7d5 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -5,6 +5,7 @@
  *
  * Copyright (c) 2010 Nokia Corporation
  * Author: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
+ * Copyright (c) 2011 Texas Instruments Incorporated
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as published
@@ -22,12 +23,18 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/omap-dma.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/delay.h>
 #include <linux/crypto.h>
 #include <linux/cryptohash.h>
@@ -37,16 +44,17 @@
 #include <crypto/hash.h>
 #include <crypto/internal/hash.h>
 
-#include <linux/omap-dma.h>
-#include <mach/irqs.h>
-
-#define SHA_REG_DIGEST(x)		(0x00 + ((x) * 0x04))
-#define SHA_REG_DIN(x)			(0x1C + ((x) * 0x04))
-
 #define SHA1_MD5_BLOCK_SIZE		SHA1_BLOCK_SIZE
 #define MD5_DIGEST_SIZE			16
 
-#define SHA_REG_DIGCNT			0x14
+#define DST_MAXBURST			16
+#define DMA_MIN				(DST_MAXBURST * sizeof(u32))
+
+#define SHA_REG_IDIGEST(dd, x)		((dd)->pdata->idigest_ofs + ((x)*0x04))
+#define SHA_REG_DIN(dd, x)		((dd)->pdata->din_ofs + ((x) * 0x04))
+#define SHA_REG_DIGCNT(dd)		((dd)->pdata->digcnt_ofs)
+
+#define SHA_REG_ODIGEST(x)		(0x00 + ((x) * 0x04))
 
 #define SHA_REG_CTRL			0x18
 #define SHA_REG_CTRL_LENGTH		(0xFFFFFFFF << 5)
@@ -56,19 +64,42 @@
 #define SHA_REG_CTRL_INPUT_READY	(1 << 1)
 #define SHA_REG_CTRL_OUTPUT_READY	(1 << 0)
 
-#define SHA_REG_REV			0x5C
-#define SHA_REG_REV_MAJOR		0xF0
-#define SHA_REG_REV_MINOR		0x0F
+#define SHA_REG_REV(dd)			((dd)->pdata->rev_ofs)
 
-#define SHA_REG_MASK			0x60
+#define SHA_REG_MASK(dd)		((dd)->pdata->mask_ofs)
 #define SHA_REG_MASK_DMA_EN		(1 << 3)
 #define SHA_REG_MASK_IT_EN		(1 << 2)
 #define SHA_REG_MASK_SOFTRESET		(1 << 1)
 #define SHA_REG_AUTOIDLE		(1 << 0)
 
-#define SHA_REG_SYSSTATUS		0x64
+#define SHA_REG_SYSSTATUS(dd)		((dd)->pdata->sysstatus_ofs)
 #define SHA_REG_SYSSTATUS_RESETDONE	(1 << 0)
 
+#define SHA_REG_MODE			0x44
+#define SHA_REG_MODE_HMAC_OUTER_HASH	(1 << 7)
+#define SHA_REG_MODE_HMAC_KEY_PROC	(1 << 5)
+#define SHA_REG_MODE_CLOSE_HASH		(1 << 4)
+#define SHA_REG_MODE_ALGO_CONSTANT	(1 << 3)
+#define SHA_REG_MODE_ALGO_MASK		(3 << 1)
+#define		SHA_REG_MODE_ALGO_MD5_128	(0 << 1)
+#define		SHA_REG_MODE_ALGO_SHA1_160	(1 << 1)
+#define		SHA_REG_MODE_ALGO_SHA2_224	(2 << 1)
+#define		SHA_REG_MODE_ALGO_SHA2_256	(3 << 1)
+
+#define SHA_REG_LENGTH			0x48
+
+#define SHA_REG_IRQSTATUS		0x118
+#define SHA_REG_IRQSTATUS_CTX_RDY	(1 << 3)
+#define SHA_REG_IRQSTATUS_PARTHASH_RDY (1 << 2)
+#define SHA_REG_IRQSTATUS_INPUT_RDY	(1 << 1)
+#define SHA_REG_IRQSTATUS_OUTPUT_RDY	(1 << 0)
+
+#define SHA_REG_IRQENA			0x11C
+#define SHA_REG_IRQENA_CTX_RDY		(1 << 3)
+#define SHA_REG_IRQENA_PARTHASH_RDY	(1 << 2)
+#define SHA_REG_IRQENA_INPUT_RDY	(1 << 1)
+#define SHA_REG_IRQENA_OUTPUT_RDY	(1 << 0)
+
 #define DEFAULT_TIMEOUT_INTERVAL	HZ
 
 /* mostly device flags */
@@ -79,20 +110,33 @@
 #define FLAGS_INIT		4
 #define FLAGS_CPU		5
 #define FLAGS_DMA_READY		6
+#define FLAGS_AUTO_XOR		7
+#define FLAGS_BE32_SHA1		8
 /* context flags */
 #define FLAGS_FINUP		16
 #define FLAGS_SG		17
-#define FLAGS_SHA1		18
-#define FLAGS_HMAC		19
-#define FLAGS_ERROR		20
 
-#define OP_UPDATE	1
-#define OP_FINAL	2
+#define FLAGS_MODE_SHIFT	18
+#define FLAGS_MODE_MASK		(SHA_REG_MODE_ALGO_MASK			\
+					<< (FLAGS_MODE_SHIFT - 1))
+#define		FLAGS_MODE_MD5		(SHA_REG_MODE_ALGO_MD5_128	\
+						<< (FLAGS_MODE_SHIFT - 1))
+#define		FLAGS_MODE_SHA1		(SHA_REG_MODE_ALGO_SHA1_160	\
+						<< (FLAGS_MODE_SHIFT - 1))
+#define		FLAGS_MODE_SHA224	(SHA_REG_MODE_ALGO_SHA2_224	\
+						<< (FLAGS_MODE_SHIFT - 1))
+#define		FLAGS_MODE_SHA256	(SHA_REG_MODE_ALGO_SHA2_256	\
+						<< (FLAGS_MODE_SHIFT - 1))
+#define FLAGS_HMAC		20
+#define FLAGS_ERROR		21
+
+#define OP_UPDATE		1
+#define OP_FINAL		2
 
 #define OMAP_ALIGN_MASK		(sizeof(u32)-1)
 #define OMAP_ALIGNED		__attribute__((aligned(sizeof(u32))))
 
-#define BUFLEN		PAGE_SIZE
+#define BUFLEN			PAGE_SIZE
 
 struct omap_sham_dev;
 
@@ -101,7 +145,7 @@ struct omap_sham_reqctx {
 	unsigned long		flags;
 	unsigned long		op;
 
-	u8			digest[SHA1_DIGEST_SIZE] OMAP_ALIGNED;
+	u8			digest[SHA256_DIGEST_SIZE] OMAP_ALIGNED;
 	size_t			digcnt;
 	size_t			bufcnt;
 	size_t			buflen;
@@ -109,6 +153,7 @@ struct omap_sham_reqctx {
 
 	/* walk state */
 	struct scatterlist	*sg;
+	struct scatterlist	sgl;
 	unsigned int		offset;	/* offset in current sg */
 	unsigned int		total;	/* total request */
 
@@ -117,8 +162,8 @@ struct omap_sham_reqctx {
 
 struct omap_sham_hmac_ctx {
 	struct crypto_shash	*shash;
-	u8			ipad[SHA1_MD5_BLOCK_SIZE];
-	u8			opad[SHA1_MD5_BLOCK_SIZE];
+	u8			ipad[SHA1_MD5_BLOCK_SIZE] OMAP_ALIGNED;
+	u8			opad[SHA1_MD5_BLOCK_SIZE] OMAP_ALIGNED;
 };
 
 struct omap_sham_ctx {
@@ -134,22 +179,56 @@ struct omap_sham_ctx {
 
 #define OMAP_SHAM_QUEUE_LENGTH	1
 
+struct omap_sham_algs_info {
+	struct ahash_alg	*algs_list;
+	unsigned int		size;
+	unsigned int		registered;
+};
+
+struct omap_sham_pdata {
+	struct omap_sham_algs_info	*algs_info;
+	unsigned int	algs_info_size;
+	unsigned long	flags;
+	int		digest_size;
+
+	void		(*copy_hash)(struct ahash_request *req, int out);
+	void		(*write_ctrl)(struct omap_sham_dev *dd, size_t length,
+				      int final, int dma);
+	void		(*trigger)(struct omap_sham_dev *dd, size_t length);
+	int		(*poll_irq)(struct omap_sham_dev *dd);
+	irqreturn_t	(*intr_hdlr)(int irq, void *dev_id);
+
+	u32		odigest_ofs;
+	u32		idigest_ofs;
+	u32		din_ofs;
+	u32		digcnt_ofs;
+	u32		rev_ofs;
+	u32		mask_ofs;
+	u32		sysstatus_ofs;
+
+	u32		major_mask;
+	u32		major_shift;
+	u32		minor_mask;
+	u32		minor_shift;
+};
+
 struct omap_sham_dev {
 	struct list_head	list;
 	unsigned long		phys_base;
 	struct device		*dev;
 	void __iomem		*io_base;
 	int			irq;
-	struct clk		*iclk;
 	spinlock_t		lock;
 	int			err;
-	int			dma;
-	int			dma_lch;
+	unsigned int		dma;
+	struct dma_chan		*dma_lch;
 	struct tasklet_struct	done_task;
 
 	unsigned long		flags;
 	struct crypto_queue	queue;
 	struct ahash_request	*req;
+
+	const struct omap_sham_pdata	*pdata;
 };
 
 struct omap_sham_drv {
@@ -197,21 +276,44 @@ static inline int omap_sham_wait(struct omap_sham_dev *dd, u32 offset, u32 bit)
 	return 0;
 }
 
-static void omap_sham_copy_hash(struct ahash_request *req, int out)
+static void omap_sham_copy_hash_omap2(struct ahash_request *req, int out)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
+	struct omap_sham_dev *dd = ctx->dd;
 	u32 *hash = (u32 *)ctx->digest;
 	int i;
 
-	/* MD5 is almost unused. So copy sha1 size to reduce code */
-	for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++) {
+	for (i = 0; i < dd->pdata->digest_size / sizeof(u32); i++) {
 		if (out)
-			hash[i] = omap_sham_read(ctx->dd,
-						SHA_REG_DIGEST(i));
+			hash[i] = omap_sham_read(dd, SHA_REG_IDIGEST(dd, i));
 		else
-			omap_sham_write(ctx->dd,
-					SHA_REG_DIGEST(i), hash[i]);
+			omap_sham_write(dd, SHA_REG_IDIGEST(dd, i), hash[i]);
+	}
+}
+
+static void omap_sham_copy_hash_omap4(struct ahash_request *req, int out)
+{
+	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
+	struct omap_sham_dev *dd = ctx->dd;
+	int i;
+
+	if (ctx->flags & BIT(FLAGS_HMAC)) {
+		struct crypto_ahash *tfm = crypto_ahash_reqtfm(dd->req);
+		struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
+		struct omap_sham_hmac_ctx *bctx = tctx->base;
+		u32 *opad = (u32 *)bctx->opad;
+
+		for (i = 0; i < dd->pdata->digest_size / sizeof(u32); i++) {
+			if (out)
+				opad[i] = omap_sham_read(dd,
+						SHA_REG_ODIGEST(i));
+			else
+				omap_sham_write(dd, SHA_REG_ODIGEST(i),
+						opad[i]);
+		}
 	}
+
+	omap_sham_copy_hash_omap2(req, out);
 }
 
 static void omap_sham_copy_ready_hash(struct ahash_request *req)
@@ -219,34 +321,44 @@ static void omap_sham_copy_ready_hash(struct ahash_request *req)
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
 	u32 *in = (u32 *)ctx->digest;
 	u32 *hash = (u32 *)req->result;
-	int i;
+	int i, d, big_endian = 0;
 
 	if (!hash)
 		return;
 
-	if (likely(ctx->flags & BIT(FLAGS_SHA1))) {
-		/* SHA1 results are in big endian */
-		for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++)
+	switch (ctx->flags & FLAGS_MODE_MASK) {
+	case FLAGS_MODE_MD5:
+		d = MD5_DIGEST_SIZE / sizeof(u32);
+		break;
+	case FLAGS_MODE_SHA1:
+		/* OMAP2 SHA1 is big endian */
+		if (test_bit(FLAGS_BE32_SHA1, &ctx->dd->flags))
+			big_endian = 1;
+		d = SHA1_DIGEST_SIZE / sizeof(u32);
+		break;
+	case FLAGS_MODE_SHA224:
+		d = SHA224_DIGEST_SIZE / sizeof(u32);
+		break;
+	case FLAGS_MODE_SHA256:
+		d = SHA256_DIGEST_SIZE / sizeof(u32);
+		break;
+	default:
+		d = 0;
+	}
+
+	if (big_endian)
+		for (i = 0; i < d; i++)
 			hash[i] = be32_to_cpu(in[i]);
-	} else {
-		/* MD5 results are in little endian */
-		for (i = 0; i < MD5_DIGEST_SIZE / sizeof(u32); i++)
+	else
+		for (i = 0; i < d; i++)
 			hash[i] = le32_to_cpu(in[i]);
-	}
 }
 
 static int omap_sham_hw_init(struct omap_sham_dev *dd)
 {
-	clk_enable(dd->iclk);
+	pm_runtime_get_sync(dd->dev);
 
 	if (!test_bit(FLAGS_INIT, &dd->flags)) {
-		omap_sham_write_mask(dd, SHA_REG_MASK,
-			SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET);
-
-		if (omap_sham_wait(dd, SHA_REG_SYSSTATUS,
-					SHA_REG_SYSSTATUS_RESETDONE))
-			return -ETIMEDOUT;
-
 		set_bit(FLAGS_INIT, &dd->flags);
 		dd->err = 0;
 	}
@@ -254,23 +366,23 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd)
 	return 0;
 }
 
-static void omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length,
+static void omap_sham_write_ctrl_omap2(struct omap_sham_dev *dd, size_t length,
 				 int final, int dma)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
 	u32 val = length << 5, mask;
 
 	if (likely(ctx->digcnt))
-		omap_sham_write(dd, SHA_REG_DIGCNT, ctx->digcnt);
+		omap_sham_write(dd, SHA_REG_DIGCNT(dd), ctx->digcnt);
 
-	omap_sham_write_mask(dd, SHA_REG_MASK,
+	omap_sham_write_mask(dd, SHA_REG_MASK(dd),
 		SHA_REG_MASK_IT_EN | (dma ? SHA_REG_MASK_DMA_EN : 0),
 		SHA_REG_MASK_IT_EN | SHA_REG_MASK_DMA_EN);
 	/*
 	 * Setting ALGO_CONST only for the first iteration
 	 * and CLOSE_HASH only for the last one.
 	 */
-	if (ctx->flags & BIT(FLAGS_SHA1))
+	if ((ctx->flags & FLAGS_MODE_MASK) == FLAGS_MODE_SHA1)
 		val |= SHA_REG_CTRL_ALGO;
 	if (!ctx->digcnt)
 		val |= SHA_REG_CTRL_ALGO_CONST;
@@ -283,6 +395,81 @@ static void omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length,
 	omap_sham_write_mask(dd, SHA_REG_CTRL, val, mask);
 }
 
+static void omap_sham_trigger_omap2(struct omap_sham_dev *dd, size_t length)
+{
+}
+
+static int omap_sham_poll_irq_omap2(struct omap_sham_dev *dd)
+{
+	return omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY);
+}
+
+static void omap_sham_write_n(struct omap_sham_dev *dd, u32 offset,
+				    u32 *value, int count)
+{
+	for (; count--; value++, offset += 4)
+		omap_sham_write(dd, offset, *value);
+}
+
+static void omap_sham_write_ctrl_omap4(struct omap_sham_dev *dd, size_t length,
+				 int final, int dma)
+{
+	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
+	u32 val, mask;
+
+	/*
+	 * Setting ALGO_CONST only for the first iteration and
+	 * CLOSE_HASH only for the last one. Note that flags mode bits
+	 * correspond to algorithm encoding in mode register.
+	 */
+	val = (ctx->flags & FLAGS_MODE_MASK) >> (FLAGS_MODE_SHIFT - 1);
+	if (!ctx->digcnt) {
+		struct crypto_ahash *tfm = crypto_ahash_reqtfm(dd->req);
+		struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
+		struct omap_sham_hmac_ctx *bctx = tctx->base;
+
+		val |= SHA_REG_MODE_ALGO_CONSTANT;
+
+		if (ctx->flags & BIT(FLAGS_HMAC)) {
+			val |= SHA_REG_MODE_HMAC_KEY_PROC;
+			omap_sham_write_n(dd, SHA_REG_ODIGEST(0),
+					  (u32 *)bctx->ipad,
+					  SHA1_BLOCK_SIZE / sizeof(u32));
+			ctx->digcnt += SHA1_BLOCK_SIZE;
+		}
+	}
+
+	if (final) {
+		val |= SHA_REG_MODE_CLOSE_HASH;
+
+		if (ctx->flags & BIT(FLAGS_HMAC))
+			val |= SHA_REG_MODE_HMAC_OUTER_HASH;
+	}
+
+	mask = SHA_REG_MODE_ALGO_CONSTANT | SHA_REG_MODE_CLOSE_HASH |
+	       SHA_REG_MODE_ALGO_MASK | SHA_REG_MODE_HMAC_OUTER_HASH |
+	       SHA_REG_MODE_HMAC_KEY_PROC;
+
+	dev_dbg(dd->dev, "ctrl: %08x, flags: %08lx\n", val, ctx->flags);
+	omap_sham_write_mask(dd, SHA_REG_MODE, val, mask);
+	omap_sham_write(dd, SHA_REG_IRQENA, SHA_REG_IRQENA_OUTPUT_RDY);
+	omap_sham_write_mask(dd, SHA_REG_MASK(dd),
+			     SHA_REG_MASK_IT_EN |
+				     (dma ? SHA_REG_MASK_DMA_EN : 0),
+			     SHA_REG_MASK_IT_EN | SHA_REG_MASK_DMA_EN);
+}
+
+static void omap_sham_trigger_omap4(struct omap_sham_dev *dd, size_t length)
+{
+	omap_sham_write(dd, SHA_REG_LENGTH, length);
+}
+
+static int omap_sham_poll_irq_omap4(struct omap_sham_dev *dd)
+{
+	return omap_sham_wait(dd, SHA_REG_IRQSTATUS,
+			      SHA_REG_IRQSTATUS_INPUT_RDY);
+}
+
 static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
 			      size_t length, int final)
 {
@@ -293,12 +480,13 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
 	dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d\n",
 						ctx->digcnt, length, final);
 
-	omap_sham_write_ctrl(dd, length, final, 0);
+	dd->pdata->write_ctrl(dd, length, final, 0);
+	dd->pdata->trigger(dd, length);
 
 	/* should be non-zero before next lines to disable clocks later */
 	ctx->digcnt += length;
 
-	if (omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY))
+	if (dd->pdata->poll_irq(dd))
 		return -ETIMEDOUT;
 
 	if (final)
@@ -309,30 +497,73 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
 	len32 = DIV_ROUND_UP(length, sizeof(u32));
 
 	for (count = 0; count < len32; count++)
-		omap_sham_write(dd, SHA_REG_DIN(count), buffer[count]);
+		omap_sham_write(dd, SHA_REG_DIN(dd, count), buffer[count]);
 
 	return -EINPROGRESS;
 }
 
+static void omap_sham_dma_callback(void *param)
+{
+	struct omap_sham_dev *dd = param;
+
+	set_bit(FLAGS_DMA_READY, &dd->flags);
+	tasklet_schedule(&dd->done_task);
+}
+
 static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
-			      size_t length, int final)
+			      size_t length, int final, int is_sg)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
-	int len32;
+	struct dma_async_tx_descriptor *tx;
+	struct dma_slave_config cfg;
+	int len32, ret;
 
 	dev_dbg(dd->dev, "xmit_dma: digcnt: %d, length: %d, final: %d\n",
 						ctx->digcnt, length, final);
 
-	len32 = DIV_ROUND_UP(length, sizeof(u32));
+	memset(&cfg, 0, sizeof(cfg));
+
+	cfg.dst_addr = dd->phys_base + SHA_REG_DIN(dd, 0);
+	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.dst_maxburst = DST_MAXBURST;
+
+	ret = dmaengine_slave_config(dd->dma_lch, &cfg);
+	if (ret) {
+		pr_err("omap-sham: can't configure dmaengine slave: %d\n", ret);
+		return ret;
+	}
 
-	omap_set_dma_transfer_params(dd->dma_lch, OMAP_DMA_DATA_TYPE_S32, len32,
-			1, OMAP_DMA_SYNC_PACKET, dd->dma,
-				OMAP_DMA_DST_SYNC_PREFETCH);
+	len32 = DIV_ROUND_UP(length, DMA_MIN) * DMA_MIN;
+
+	if (is_sg) {
+		/*
+		 * The SG entry passed in may not have the 'length' member
+		 * set correctly so use a local SG entry (sgl) with the
+		 * proper value for 'length' instead.  If this is not done,
+		 * the dmaengine may try to DMA the incorrect amount of data.
+		 */
+		sg_init_table(&ctx->sgl, 1);
+		ctx->sgl.page_link = ctx->sg->page_link;
+		ctx->sgl.offset = ctx->sg->offset;
+		sg_dma_len(&ctx->sgl) = len32;
+		sg_dma_address(&ctx->sgl) = sg_dma_address(ctx->sg);
+
+		tx = dmaengine_prep_slave_sg(dd->dma_lch, &ctx->sgl, 1,
+			DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	} else {
+		tx = dmaengine_prep_slave_single(dd->dma_lch, dma_addr, len32,
+			DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	}
+
+	if (!tx) {
+		dev_err(dd->dev, "prep_slave_sg/single() failed\n");
+		return -EINVAL;
+	}
 
-	omap_set_dma_src_params(dd->dma_lch, 0, OMAP_DMA_AMODE_POST_INC,
-				dma_addr, 0, 0);
+	tx->callback = omap_sham_dma_callback;
+	tx->callback_param = dd;
 
-	omap_sham_write_ctrl(dd, length, final, 1);
+	dd->pdata->write_ctrl(dd, length, final, 1);
 
 	ctx->digcnt += length;
 
@@ -341,7 +572,10 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
 
 	set_bit(FLAGS_DMA_ACTIVE, &dd->flags);
 
-	omap_start_dma(dd->dma_lch);
+	dmaengine_submit(tx);
+	dma_async_issue_pending(dd->dma_lch);
+
+	dd->pdata->trigger(dd, length);
 
 	return -EINPROGRESS;
 }
@@ -388,6 +622,8 @@ static int omap_sham_xmit_dma_map(struct omap_sham_dev *dd,
 					struct omap_sham_reqctx *ctx,
 					size_t length, int final)
 {
+	int ret;
+
 	ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer, ctx->buflen,
 				       DMA_TO_DEVICE);
 	if (dma_mapping_error(dd->dev, ctx->dma_addr)) {
@@ -397,8 +633,12 @@ static int omap_sham_xmit_dma_map(struct omap_sham_dev *dd,
 
 	ctx->flags &= ~BIT(FLAGS_SG);
 
-	/* next call does not fail... so no unmap in the case of error */
-	return omap_sham_xmit_dma(dd, ctx->dma_addr, length, final);
+	ret = omap_sham_xmit_dma(dd, ctx->dma_addr, length, final, 0);
+	if (ret != -EINPROGRESS)
+		dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen,
+				 DMA_TO_DEVICE);
+
+	return ret;
 }
 
 static int omap_sham_update_dma_slow(struct omap_sham_dev *dd)
@@ -433,6 +673,7 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
 	unsigned int length, final, tail;
 	struct scatterlist *sg;
+	int ret;
 
 	if (!ctx->total)
 		return 0;
@@ -440,6 +681,15 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
 	if (ctx->bufcnt || ctx->offset)
 		return omap_sham_update_dma_slow(dd);
 
+	/*
+	 * Don't use the sg interface when the transfer size is less
+	 * than the number of elements in a DMA frame.  Otherwise,
+	 * the dmaengine infrastructure will calculate that it needs
+	 * to transfer 0 frames which ultimately fails.
+	 */
+	if (ctx->total < (DST_MAXBURST * sizeof(u32)))
+		return omap_sham_update_dma_slow(dd);
+
 	dev_dbg(dd->dev, "fast: digcnt: %d, bufcnt: %u, total: %u\n",
 			ctx->digcnt, ctx->bufcnt, ctx->total);
 
@@ -477,8 +727,11 @@ static int omap_sham_update_dma_start(struct omap_sham_dev *dd)
 
 	final = (ctx->flags & BIT(FLAGS_FINUP)) && !ctx->total;
 
-	/* next call does not fail... so no unmap in the case of error */
-	return omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, final);
+	ret = omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, final, 1);
+	if (ret != -EINPROGRESS)
+		dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
+
+	return ret;
 }
 
 static int omap_sham_update_cpu(struct omap_sham_dev *dd)
@@ -497,7 +750,8 @@ static int omap_sham_update_dma_stop(struct omap_sham_dev *dd)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
 
-	omap_stop_dma(dd->dma_lch);
+	dmaengine_terminate_all(dd->dma_lch);
+
 	if (ctx->flags & BIT(FLAGS_SG)) {
 		dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
 		if (ctx->sg->length == ctx->offset) {
@@ -539,18 +793,33 @@ static int omap_sham_init(struct ahash_request *req)
 	dev_dbg(dd->dev, "init: digest size: %d\n",
 		crypto_ahash_digestsize(tfm));
 
-	if (crypto_ahash_digestsize(tfm) == SHA1_DIGEST_SIZE)
-		ctx->flags |= BIT(FLAGS_SHA1);
+	switch (crypto_ahash_digestsize(tfm)) {
+	case MD5_DIGEST_SIZE:
+		ctx->flags |= FLAGS_MODE_MD5;
+		break;
+	case SHA1_DIGEST_SIZE:
+		ctx->flags |= FLAGS_MODE_SHA1;
+		break;
+	case SHA224_DIGEST_SIZE:
+		ctx->flags |= FLAGS_MODE_SHA224;
+		break;
+	case SHA256_DIGEST_SIZE:
+		ctx->flags |= FLAGS_MODE_SHA256;
+		break;
+	}
 
 	ctx->bufcnt = 0;
 	ctx->digcnt = 0;
 	ctx->buflen = BUFLEN;
 
 	if (tctx->flags & BIT(FLAGS_HMAC)) {
-		struct omap_sham_hmac_ctx *bctx = tctx->base;
+		if (!test_bit(FLAGS_AUTO_XOR, &dd->flags)) {
+			struct omap_sham_hmac_ctx *bctx = tctx->base;
+
+			memcpy(ctx->buffer, bctx->ipad, SHA1_MD5_BLOCK_SIZE);
+			ctx->bufcnt = SHA1_MD5_BLOCK_SIZE;
+		}
 
-		memcpy(ctx->buffer, bctx->ipad, SHA1_MD5_BLOCK_SIZE);
-		ctx->bufcnt = SHA1_MD5_BLOCK_SIZE;
 		ctx->flags |= BIT(FLAGS_HMAC);
 	}
 
@@ -584,7 +853,7 @@ static int omap_sham_final_req(struct omap_sham_dev *dd)
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
 	int err = 0, use_dma = 1;
 
-	if (ctx->bufcnt <= 64)
+	if (ctx->bufcnt <= DMA_MIN)
 		/* faster to handle last block with cpu */
 		use_dma = 0;
 
@@ -627,7 +896,8 @@ static int omap_sham_finish(struct ahash_request *req)
 
 	if (ctx->digcnt) {
 		omap_sham_copy_ready_hash(req);
-		if (ctx->flags & BIT(FLAGS_HMAC))
+		if ((ctx->flags & BIT(FLAGS_HMAC)) &&
+				!test_bit(FLAGS_AUTO_XOR, &dd->flags))
 			err = omap_sham_finish_hmac(req);
 	}
 
@@ -642,7 +912,7 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
 	struct omap_sham_dev *dd = ctx->dd;
 
 	if (!err) {
-		omap_sham_copy_hash(req, 1);
+		dd->pdata->copy_hash(req, 1);
 		if (test_bit(FLAGS_FINAL, &dd->flags))
 			err = omap_sham_finish(req);
 	} else {
@@ -652,7 +922,8 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
 	/* atomic operation is not needed here */
 	dd->flags &= ~(BIT(FLAGS_BUSY) | BIT(FLAGS_FINAL) | BIT(FLAGS_CPU) |
 			BIT(FLAGS_DMA_READY) | BIT(FLAGS_OUTPUT_READY));
-	clk_disable(dd->iclk);
+
+	pm_runtime_put_sync(dd->dev);
 
 	if (req->base.complete)
 		req->base.complete(&req->base, err);
@@ -699,19 +970,9 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd,
 	if (err)
 		goto err1;
 
-	omap_set_dma_dest_params(dd->dma_lch, 0,
-			OMAP_DMA_AMODE_CONSTANT,
-			dd->phys_base + SHA_REG_DIN(0), 0, 16);
-
-	omap_set_dma_dest_burst_mode(dd->dma_lch,
-			OMAP_DMA_DATA_BURST_16);
-
-	omap_set_dma_src_burst_mode(dd->dma_lch,
-			OMAP_DMA_DATA_BURST_4);
-
 	if (ctx->digcnt)
 		/* request has changed - restore hash */
-		omap_sham_copy_hash(req, 0);
+		dd->pdata->copy_hash(req, 0);
 
 	if (ctx->op == OP_UPDATE) {
 		err = omap_sham_update_req(dd);
@@ -850,7 +1111,21 @@ static int omap_sham_setkey(struct crypto_ahash *tfm, const u8 *key,
 	struct omap_sham_hmac_ctx *bctx = tctx->base;
 	int bs = crypto_shash_blocksize(bctx->shash);
 	int ds = crypto_shash_digestsize(bctx->shash);
+	struct omap_sham_dev *dd = NULL, *tmp;
 	int err, i;
+
+	spin_lock_bh(&sham.lock);
+	if (!tctx->dd) {
+		list_for_each_entry(tmp, &sham.dev_list, list) {
+			dd = tmp;
+			break;
+		}
+		tctx->dd = dd;
+	} else {
+		dd = tctx->dd;
+	}
+	spin_unlock_bh(&sham.lock);
+
 	err = crypto_shash_setkey(tctx->fallback, key, keylen);
 	if (err)
 		return err;
@@ -867,11 +1142,14 @@ static int omap_sham_setkey(struct crypto_ahash *tfm, const u8 *key,
 	}
 
 	memset(bctx->ipad + keylen, 0, bs - keylen);
-	memcpy(bctx->opad, bctx->ipad, bs);
 
-	for (i = 0; i < bs; i++) {
-		bctx->ipad[i] ^= 0x36;
-		bctx->opad[i] ^= 0x5c;
+	if (!test_bit(FLAGS_AUTO_XOR, &dd->flags)) {
+		memcpy(bctx->opad, bctx->ipad, bs);
+
+		for (i = 0; i < bs; i++) {
+			bctx->ipad[i] ^= 0x36;
+			bctx->opad[i] ^= 0x5c;
+		}
 	}
 
 	return err;
@@ -921,6 +1199,16 @@ static int omap_sham_cra_sha1_init(struct crypto_tfm *tfm)
 	return omap_sham_cra_init_alg(tfm, "sha1");
 }
 
+static int omap_sham_cra_sha224_init(struct crypto_tfm *tfm)
+{
+	return omap_sham_cra_init_alg(tfm, "sha224");
+}
+
+static int omap_sham_cra_sha256_init(struct crypto_tfm *tfm)
+{
+	return omap_sham_cra_init_alg(tfm, "sha256");
+}
+
 static int omap_sham_cra_md5_init(struct crypto_tfm *tfm)
 {
 	return omap_sham_cra_init_alg(tfm, "md5");
@@ -939,7 +1227,7 @@ static void omap_sham_cra_exit(struct crypto_tfm *tfm)
 	}
 }
 
-static struct ahash_alg algs[] = {
+static struct ahash_alg algs_sha1_md5[] = {
 {
 	.init		= omap_sham_init,
 	.update		= omap_sham_update,
@@ -1038,6 +1326,102 @@ static struct ahash_alg algs[] = {
 }
 };
 
+/* OMAP4 has some algs in addition to what OMAP2 has */
+static struct ahash_alg algs_sha224_sha256[] = {
+{
+	.init		= omap_sham_init,
+	.update		= omap_sham_update,
+	.final		= omap_sham_final,
+	.finup		= omap_sham_finup,
+	.digest		= omap_sham_digest,
+	.halg.digestsize	= SHA224_DIGEST_SIZE,
+	.halg.base	= {
+		.cra_name		= "sha224",
+		.cra_driver_name	= "omap-sha224",
+		.cra_priority		= 100,
+		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
+						CRYPTO_ALG_ASYNC |
+						CRYPTO_ALG_NEED_FALLBACK,
+		.cra_blocksize		= SHA224_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct omap_sham_ctx),
+		.cra_alignmask		= 0,
+		.cra_module		= THIS_MODULE,
+		.cra_init		= omap_sham_cra_init,
+		.cra_exit		= omap_sham_cra_exit,
+	}
+},
+{
+	.init		= omap_sham_init,
+	.update		= omap_sham_update,
+	.final		= omap_sham_final,
+	.finup		= omap_sham_finup,
+	.digest		= omap_sham_digest,
+	.halg.digestsize	= SHA256_DIGEST_SIZE,
+	.halg.base	= {
+		.cra_name		= "sha256",
+		.cra_driver_name	= "omap-sha256",
+		.cra_priority		= 100,
+		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
+						CRYPTO_ALG_ASYNC |
+						CRYPTO_ALG_NEED_FALLBACK,
+		.cra_blocksize		= SHA256_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct omap_sham_ctx),
+		.cra_alignmask		= 0,
+		.cra_module		= THIS_MODULE,
+		.cra_init		= omap_sham_cra_init,
+		.cra_exit		= omap_sham_cra_exit,
+	}
+},
+{
+	.init		= omap_sham_init,
+	.update		= omap_sham_update,
+	.final		= omap_sham_final,
+	.finup		= omap_sham_finup,
+	.digest		= omap_sham_digest,
+	.setkey		= omap_sham_setkey,
+	.halg.digestsize	= SHA224_DIGEST_SIZE,
+	.halg.base	= {
+		.cra_name		= "hmac(sha224)",
+		.cra_driver_name	= "omap-hmac-sha224",
+		.cra_priority		= 100,
+		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
+						CRYPTO_ALG_ASYNC |
+						CRYPTO_ALG_NEED_FALLBACK,
+		.cra_blocksize		= SHA224_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct omap_sham_ctx) +
+					sizeof(struct omap_sham_hmac_ctx),
+		.cra_alignmask		= OMAP_ALIGN_MASK,
+		.cra_module		= THIS_MODULE,
+		.cra_init		= omap_sham_cra_sha224_init,
+		.cra_exit		= omap_sham_cra_exit,
+	}
+},
+{
+	.init		= omap_sham_init,
+	.update		= omap_sham_update,
+	.final		= omap_sham_final,
+	.finup		= omap_sham_finup,
+	.digest		= omap_sham_digest,
+	.setkey		= omap_sham_setkey,
+	.halg.digestsize	= SHA256_DIGEST_SIZE,
+	.halg.base	= {
+		.cra_name		= "hmac(sha256)",
+		.cra_driver_name	= "omap-hmac-sha256",
+		.cra_priority		= 100,
+		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
+						CRYPTO_ALG_ASYNC |
+						CRYPTO_ALG_NEED_FALLBACK,
+		.cra_blocksize		= SHA256_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct omap_sham_ctx) +
+					sizeof(struct omap_sham_hmac_ctx),
+		.cra_alignmask		= OMAP_ALIGN_MASK,
+		.cra_module		= THIS_MODULE,
+		.cra_init		= omap_sham_cra_sha256_init,
+		.cra_exit		= omap_sham_cra_exit,
+	}
+},
+};
+
 static void omap_sham_done_task(unsigned long data)
 {
 	struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
@@ -1076,7 +1460,19 @@ finish:
 	omap_sham_finish_req(dd->req, err);
 }
 
-static irqreturn_t omap_sham_irq(int irq, void *dev_id)
+static irqreturn_t omap_sham_irq_common(struct omap_sham_dev *dd)
+{
+	if (!test_bit(FLAGS_BUSY, &dd->flags)) {
+		dev_warn(dd->dev, "Interrupt when no active requests.\n");
+	} else {
+		set_bit(FLAGS_OUTPUT_READY, &dd->flags);
+		tasklet_schedule(&dd->done_task);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t omap_sham_irq_omap2(int irq, void *dev_id)
 {
 	struct omap_sham_dev *dd = dev_id;
 
@@ -1088,61 +1484,184 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id)
 				 SHA_REG_CTRL_OUTPUT_READY);
 	omap_sham_read(dd, SHA_REG_CTRL);
 
-	if (!test_bit(FLAGS_BUSY, &dd->flags)) {
-		dev_warn(dd->dev, "Interrupt when no active requests.\n");
-		return IRQ_HANDLED;
-	}
-
-	set_bit(FLAGS_OUTPUT_READY, &dd->flags);
-	tasklet_schedule(&dd->done_task);
-
-	return IRQ_HANDLED;
+	return omap_sham_irq_common(dd);
 }
 
-static void omap_sham_dma_callback(int lch, u16 ch_status, void *data)
+static irqreturn_t omap_sham_irq_omap4(int irq, void *dev_id)
 {
-	struct omap_sham_dev *dd = data;
+	struct omap_sham_dev *dd = dev_id;
 
-	if (ch_status != OMAP_DMA_BLOCK_IRQ) {
-		pr_err("omap-sham DMA error status: 0x%hx\n", ch_status);
-		dd->err = -EIO;
-		clear_bit(FLAGS_INIT, &dd->flags);/* request to re-initialize */
-	}
+	omap_sham_write_mask(dd, SHA_REG_MASK(dd), 0, SHA_REG_MASK_IT_EN);
 
-	set_bit(FLAGS_DMA_READY, &dd->flags);
-	tasklet_schedule(&dd->done_task);
+	return omap_sham_irq_common(dd);
 }
 
-static int omap_sham_dma_init(struct omap_sham_dev *dd)
+static struct omap_sham_algs_info omap_sham_algs_info_omap2[] = {
+	{
+		.algs_list	= algs_sha1_md5,
+		.size		= ARRAY_SIZE(algs_sha1_md5),
+	},
+};
+
+static const struct omap_sham_pdata omap_sham_pdata_omap2 = {
+	.algs_info	= omap_sham_algs_info_omap2,
+	.algs_info_size	= ARRAY_SIZE(omap_sham_algs_info_omap2),
+	.flags		= BIT(FLAGS_BE32_SHA1),
+	.digest_size	= SHA1_DIGEST_SIZE,
+	.copy_hash	= omap_sham_copy_hash_omap2,
+	.write_ctrl	= omap_sham_write_ctrl_omap2,
+	.trigger	= omap_sham_trigger_omap2,
+	.poll_irq	= omap_sham_poll_irq_omap2,
+	.intr_hdlr	= omap_sham_irq_omap2,
+	.idigest_ofs	= 0x00,
+	.din_ofs	= 0x1c,
+	.digcnt_ofs	= 0x14,
+	.rev_ofs	= 0x5c,
+	.mask_ofs	= 0x60,
+	.sysstatus_ofs	= 0x64,
+	.major_mask	= 0xf0,
+	.major_shift	= 4,
+	.minor_mask	= 0x0f,
+	.minor_shift	= 0,
+};
+
+#ifdef CONFIG_OF
+static struct omap_sham_algs_info omap_sham_algs_info_omap4[] = {
+	{
+		.algs_list	= algs_sha1_md5,
+		.size		= ARRAY_SIZE(algs_sha1_md5),
+	},
+	{
+		.algs_list	= algs_sha224_sha256,
+		.size		= ARRAY_SIZE(algs_sha224_sha256),
+	},
+};
+
+static const struct omap_sham_pdata omap_sham_pdata_omap4 = {
+	.algs_info	= omap_sham_algs_info_omap4,
+	.algs_info_size	= ARRAY_SIZE(omap_sham_algs_info_omap4),
+	.flags		= BIT(FLAGS_AUTO_XOR),
+	.digest_size	= SHA256_DIGEST_SIZE,
+	.copy_hash	= omap_sham_copy_hash_omap4,
+	.write_ctrl	= omap_sham_write_ctrl_omap4,
+	.trigger	= omap_sham_trigger_omap4,
+	.poll_irq	= omap_sham_poll_irq_omap4,
+	.intr_hdlr	= omap_sham_irq_omap4,
+	.idigest_ofs	= 0x020,
+	.din_ofs	= 0x080,
+	.digcnt_ofs	= 0x040,
+	.rev_ofs	= 0x100,
+	.mask_ofs	= 0x110,
+	.sysstatus_ofs	= 0x114,
+	.major_mask	= 0x0700,
+	.major_shift	= 8,
+	.minor_mask	= 0x003f,
+	.minor_shift	= 0,
+};
+
+static const struct of_device_id omap_sham_of_match[] = {
+	{
+		.compatible	= "ti,omap2-sham",
+		.data		= &omap_sham_pdata_omap2,
+	},
+	{
+		.compatible	= "ti,omap4-sham",
+		.data		= &omap_sham_pdata_omap4,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, omap_sham_of_match);
+
+static int omap_sham_get_res_of(struct omap_sham_dev *dd,
+		struct device *dev, struct resource *res)
 {
-	int err;
+	struct device_node *node = dev->of_node;
+	const struct of_device_id *match;
+	int err = 0;
 
-	dd->dma_lch = -1;
+	match = of_match_device(of_match_ptr(omap_sham_of_match), dev);
+	if (!match) {
+		dev_err(dev, "no compatible OF match\n");
+		err = -EINVAL;
+		goto err;
+	}
 
-	err = omap_request_dma(dd->dma, dev_name(dd->dev),
-			omap_sham_dma_callback, dd, &dd->dma_lch);
-	if (err) {
-		dev_err(dd->dev, "Unable to request DMA channel\n");
-		return err;
+	err = of_address_to_resource(node, 0, res);
+	if (err < 0) {
+		dev_err(dev, "can't translate OF node address\n");
+		err = -EINVAL;
+		goto err;
 	}
 
-	return 0;
+	dd->irq = of_irq_to_resource(node, 0, NULL);
+	if (!dd->irq) {
+		dev_err(dev, "can't translate OF irq value\n");
+		err = -EINVAL;
+		goto err;
+	}
+
+	dd->dma = -1; /* Dummy value that's unused */
+	dd->pdata = match->data;
+
+err:
+	return err;
+}
+#else
+static int omap_sham_get_res_dev(struct omap_sham_dev *dd,
+		struct device *dev, struct resource *res)
+{
+	return -EINVAL;
 }
+#endif
 
-static void omap_sham_dma_cleanup(struct omap_sham_dev *dd)
+static int omap_sham_get_res_pdev(struct omap_sham_dev *dd,
+		struct platform_device *pdev, struct resource *res)
 {
-	if (dd->dma_lch >= 0) {
-		omap_free_dma(dd->dma_lch);
-		dd->dma_lch = -1;
+	struct device *dev = &pdev->dev;
+	struct resource *r;
+	int err = 0;
+
+	/* Get the base address */
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		dev_err(dev, "no MEM resource info\n");
+		err = -ENODEV;
+		goto err;
+	}
+	memcpy(res, r, sizeof(*res));
+
+	/* Get the IRQ */
+	dd->irq = platform_get_irq(pdev, 0);
+	if (dd->irq < 0) {
+		dev_err(dev, "no IRQ resource info\n");
+		err = dd->irq;
+		goto err;
 	}
+
+	/* Get the DMA */
+	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!r) {
+		dev_err(dev, "no DMA resource info\n");
+		err = -ENODEV;
+		goto err;
+	}
+	dd->dma = r->start;
+
+	/* Only OMAP2/3 can be non-DT */
+	dd->pdata = &omap_sham_pdata_omap2;
+
+err:
+	return err;
 }
 
 static int omap_sham_probe(struct platform_device *pdev)
 {
 	struct omap_sham_dev *dd;
 	struct device *dev = &pdev->dev;
-	struct resource *res;
+	struct resource res;
+	dma_cap_mask_t mask;
 	int err, i, j;
+	u32 rev;
 
 	dd = kzalloc(sizeof(struct omap_sham_dev), GFP_KERNEL);
 	if (dd == NULL) {
@@ -1158,89 +1677,75 @@ static int omap_sham_probe(struct platform_device *pdev)
 	tasklet_init(&dd->done_task, omap_sham_done_task, (unsigned long)dd);
 	crypto_init_queue(&dd->queue, OMAP_SHAM_QUEUE_LENGTH);
 
-	dd->irq = -1;
-
-	/* Get the base address */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "no MEM resource info\n");
-		err = -ENODEV;
-		goto res_err;
-	}
-	dd->phys_base = res->start;
-
-	/* Get the DMA */
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!res) {
-		dev_err(dev, "no DMA resource info\n");
-		err = -ENODEV;
+	err = (dev->of_node) ? omap_sham_get_res_of(dd, dev, &res) :
+			       omap_sham_get_res_pdev(dd, pdev, &res);
+	if (err)
 		goto res_err;
-	}
-	dd->dma = res->start;
 
-	/* Get the IRQ */
-	dd->irq = platform_get_irq(pdev,  0);
-	if (dd->irq < 0) {
-		dev_err(dev, "no IRQ resource info\n");
-		err = dd->irq;
+	dd->io_base = devm_request_and_ioremap(dev, &res);
+	if (!dd->io_base) {
+		dev_err(dev, "can't ioremap\n");
+		err = -ENOMEM;
 		goto res_err;
 	}
+	dd->phys_base = res.start;
 
-	err = request_irq(dd->irq, omap_sham_irq,
-			IRQF_TRIGGER_LOW, dev_name(dev), dd);
+	err = request_irq(dd->irq, dd->pdata->intr_hdlr, IRQF_TRIGGER_LOW,
+			  dev_name(dev), dd);
 	if (err) {
 		dev_err(dev, "unable to request irq.\n");
 		goto res_err;
 	}
 
-	err = omap_sham_dma_init(dd);
-	if (err)
-		goto dma_err;
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
 
-	/* Initializing the clock */
-	dd->iclk = clk_get(dev, "ick");
-	if (IS_ERR(dd->iclk)) {
-		dev_err(dev, "clock intialization failed.\n");
-		err = PTR_ERR(dd->iclk);
-		goto clk_err;
+	dd->dma_lch = dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+						       &dd->dma, dev, "rx");
+	if (!dd->dma_lch) {
+		dev_err(dev, "unable to obtain RX DMA engine channel %u\n",
+			dd->dma);
+		err = -ENXIO;
+		goto dma_err;
 	}
 
-	dd->io_base = ioremap(dd->phys_base, SZ_4K);
-	if (!dd->io_base) {
-		dev_err(dev, "can't ioremap\n");
-		err = -ENOMEM;
-		goto io_err;
-	}
+	dd->flags |= dd->pdata->flags;
+
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
+	rev = omap_sham_read(dd, SHA_REG_REV(dd));
+	pm_runtime_put_sync(&pdev->dev);
 
-	clk_enable(dd->iclk);
 	dev_info(dev, "hw accel on OMAP rev %u.%u\n",
-		(omap_sham_read(dd, SHA_REG_REV) & SHA_REG_REV_MAJOR) >> 4,
-		omap_sham_read(dd, SHA_REG_REV) & SHA_REG_REV_MINOR);
-	clk_disable(dd->iclk);
+		(rev & dd->pdata->major_mask) >> dd->pdata->major_shift,
+		(rev & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
 
 	spin_lock(&sham.lock);
 	list_add_tail(&dd->list, &sham.dev_list);
 	spin_unlock(&sham.lock);
 
-	for (i = 0; i < ARRAY_SIZE(algs); i++) {
-		err = crypto_register_ahash(&algs[i]);
-		if (err)
-			goto err_algs;
+	for (i = 0; i < dd->pdata->algs_info_size; i++) {
+		for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
+			err = crypto_register_ahash(
+					&dd->pdata->algs_info[i].algs_list[j]);
+			if (err)
+				goto err_algs;
+
+			dd->pdata->algs_info[i].registered++;
+		}
 	}
 
 	return 0;
 
 err_algs:
-	for (j = 0; j < i; j++)
-		crypto_unregister_ahash(&algs[j]);
-	iounmap(dd->io_base);
-io_err:
-	clk_put(dd->iclk);
-clk_err:
-	omap_sham_dma_cleanup(dd);
+	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
+		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
+			crypto_unregister_ahash(
+					&dd->pdata->algs_info[i].algs_list[j]);
+	pm_runtime_disable(dev);
+	dma_release_channel(dd->dma_lch);
 dma_err:
-	if (dd->irq >= 0)
-		free_irq(dd->irq, dd);
+	free_irq(dd->irq, dd);
 res_err:
 	kfree(dd);
 	dd = NULL;
@@ -1253,7 +1758,7 @@ data_err:
 static int omap_sham_remove(struct platform_device *pdev)
 {
 	static struct omap_sham_dev *dd;
-	int i;
+	int i, j;
 
 	dd = platform_get_drvdata(pdev);
 	if (!dd)
@@ -1261,33 +1766,51 @@ static int omap_sham_remove(struct platform_device *pdev)
 	spin_lock(&sham.lock);
 	list_del(&dd->list);
 	spin_unlock(&sham.lock);
-	for (i = 0; i < ARRAY_SIZE(algs); i++)
-		crypto_unregister_ahash(&algs[i]);
+	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
+		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
+			crypto_unregister_ahash(
+					&dd->pdata->algs_info[i].algs_list[j]);
 	tasklet_kill(&dd->done_task);
-	iounmap(dd->io_base);
-	clk_put(dd->iclk);
-	omap_sham_dma_cleanup(dd);
-	if (dd->irq >= 0)
-		free_irq(dd->irq, dd);
+	pm_runtime_disable(&pdev->dev);
+	dma_release_channel(dd->dma_lch);
+	free_irq(dd->irq, dd);
 	kfree(dd);
 	dd = NULL;
 
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int omap_sham_suspend(struct device *dev)
+{
+	pm_runtime_put_sync(dev);
+	return 0;
+}
+
+static int omap_sham_resume(struct device *dev)
+{
+	pm_runtime_get_sync(dev);
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops omap_sham_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(omap_sham_suspend, omap_sham_resume)
+};
+
 static struct platform_driver omap_sham_driver = {
 	.probe	= omap_sham_probe,
 	.remove	= omap_sham_remove,
 	.driver	= {
 		.name	= "omap-sham",
 		.owner	= THIS_MODULE,
+		.pm	= &omap_sham_pm_ops,
+		.of_match_table	= omap_sham_of_match,
 	},
 };
 
 static int __init omap_sham_mod_init(void)
 {
-	pr_info("loading %s driver\n", "omap-sham");
-
 	return platform_driver_register(&omap_sham_driver);
 }
 
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d4c1218..20ef955 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -221,7 +221,7 @@ config SIRF_DMA
 
 config TI_EDMA
 	tristate "TI EDMA support"
-	depends on ARCH_DAVINCI
+	depends on ARCH_DAVINCI || ARCH_OMAP
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
 	default n
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/edma.c b/drivers/dma/edma.c
index f424298..2e27ec5 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-#include <mach/edma.h>
+#include <linux/platform_data/edma.h>
 
 #include "dmaengine.h"
 #include "virt-dma.h"
@@ -69,9 +69,8 @@ struct edma_chan {
 	int				ch_num;
 	bool				alloced;
 	int				slot[EDMA_MAX_SLOTS];
-	dma_addr_t			addr;
-	int				addr_width;
-	int				maxburst;
+	struct dma_slave_config		cfg;
+	struct dmaengine_chan_caps	caps;
 };
 
 struct edma_cc {
@@ -178,29 +177,14 @@ static int edma_terminate_all(struct edma_chan *echan)
 	return 0;
 }
 
-
 static int edma_slave_config(struct edma_chan *echan,
-	struct dma_slave_config *config)
+	struct dma_slave_config *cfg)
 {
-	if ((config->src_addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES) ||
-	    (config->dst_addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
+	if (cfg->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES ||
+	    cfg->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
 		return -EINVAL;
 
-	if (config->direction == DMA_MEM_TO_DEV) {
-		if (config->dst_addr)
-			echan->addr = config->dst_addr;
-		if (config->dst_addr_width)
-			echan->addr_width = config->dst_addr_width;
-		if (config->dst_maxburst)
-			echan->maxburst = config->dst_maxburst;
-	} else if (config->direction == DMA_DEV_TO_MEM) {
-		if (config->src_addr)
-			echan->addr = config->src_addr;
-		if (config->src_addr_width)
-			echan->addr_width = config->src_addr_width;
-		if (config->src_maxburst)
-			echan->maxburst = config->src_maxburst;
-	}
+	memcpy(&echan->cfg, cfg, sizeof(echan->cfg));
 
 	return 0;
 }
@@ -235,6 +219,9 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
 	struct edma_chan *echan = to_edma_chan(chan);
 	struct device *dev = chan->device->dev;
 	struct edma_desc *edesc;
+	dma_addr_t dev_addr;
+	enum dma_slave_buswidth dev_width;
+	u32 burst;
 	struct scatterlist *sg;
 	int i;
 	int acnt, bcnt, ccnt, src, dst, cidx;
@@ -243,7 +230,20 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
 	if (unlikely(!echan || !sgl || !sg_len))
 		return NULL;
 
-	if (echan->addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) {
+	if (direction == DMA_DEV_TO_MEM) {
+		dev_addr = echan->cfg.src_addr;
+		dev_width = echan->cfg.src_addr_width;
+		burst = echan->cfg.src_maxburst;
+	} else if (direction == DMA_MEM_TO_DEV) {
+		dev_addr = echan->cfg.dst_addr;
+		dev_width = echan->cfg.dst_addr_width;
+		burst = echan->cfg.dst_maxburst;
+	} else {
+		dev_err(dev, "%s: bad direction?\n", __func__);
+		return NULL;
+	}
+
+	if (dev_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) {
 		dev_err(dev, "Undefined slave buswidth\n");
 		return NULL;
 	}
@@ -275,14 +275,14 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
 			}
 		}
 
-		acnt = echan->addr_width;
+		acnt = dev_width;
 
 		/*
 		 * If the maxburst is equal to the fifo width, use
 		 * A-synced transfers. This allows for large contiguous
 		 * buffer transfers using only one PaRAM set.
 		 */
-		if (echan->maxburst == 1) {
+		if (burst == 1) {
 			edesc->absync = false;
 			ccnt = sg_dma_len(sg) / acnt / (SZ_64K - 1);
 			bcnt = sg_dma_len(sg) / acnt - ccnt * (SZ_64K - 1);
@@ -302,7 +302,7 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
 		 */
 		} else {
 			edesc->absync = true;
-			bcnt = echan->maxburst;
+			bcnt = burst;
 			ccnt = sg_dma_len(sg) / (acnt * bcnt);
 			if (ccnt > (SZ_64K - 1)) {
 				dev_err(dev, "Exceeded max SG segment size\n");
@@ -313,13 +313,13 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
 
 		if (direction == DMA_MEM_TO_DEV) {
 			src = sg_dma_address(sg);
-			dst = echan->addr;
+			dst = dev_addr;
 			src_bidx = acnt;
 			src_cidx = cidx;
 			dst_bidx = 0;
 			dst_cidx = 0;
 		} else {
-			src = echan->addr;
+			src = dev_addr;
 			dst = sg_dma_address(sg);
 			src_bidx = 0;
 			src_cidx = 0;
@@ -395,8 +395,11 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
 	a_ch_num = edma_alloc_channel(echan->ch_num, edma_callback,
 					chan, EVENTQ_DEFAULT);
 
+	/* NOTE: DO NOT RETURN ENODEV */
+	/* It causes dmaengine to remove the device from it's list */
+
 	if (a_ch_num < 0) {
-		ret = -ENODEV;
+		ret = -EINVAL;
 		goto err_no_chan;
 	}
 
@@ -404,7 +407,7 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
 		dev_err(dev, "failed to allocate requested channel %u:%u\n",
 			EDMA_CTLR(echan->ch_num),
 			EDMA_CHAN_SLOT(echan->ch_num));
-		ret = -ENODEV;
+		ret = -EINVAL;
 		goto err_wrong_chan;
 	}
 
@@ -463,6 +466,28 @@ static void edma_issue_pending(struct dma_chan *chan)
 	spin_unlock_irqrestore(&echan->vchan.lock, flags);
 }
 
+static struct dmaengine_chan_caps
+*edma_get_channel_caps(struct dma_chan *chan, enum dma_transfer_direction dir)
+{
+	struct edma_chan *echan;
+	enum dma_slave_buswidth width = 0;
+	u32 burst = 0;
+
+	if (chan) {
+		echan = to_edma_chan(chan);
+		if (dir == DMA_MEM_TO_DEV) {
+			width = echan->cfg.dst_addr_width;
+			burst = echan->cfg.dst_maxburst;
+		} else if (dir == DMA_DEV_TO_MEM) {
+			width = echan->cfg.src_addr_width;
+			burst = echan->cfg.src_maxburst;
+		}
+		echan->caps.seg_len = (SZ_64K - 1) * width * burst;
+		return &echan->caps;
+	}
+	return NULL;
+}
+
 static size_t edma_desc_size(struct edma_desc *edesc)
 {
 	int i;
@@ -522,6 +547,9 @@ static void __init edma_chan_init(struct edma_cc *ecc,
 		echan->ch_num = EDMA_CTLR_CHAN(ecc->ctlr, i);
 		echan->ecc = ecc;
 		echan->vchan.desc_free = edma_desc_free;
+		dma_cap_set(DMA_SLAVE, echan->caps.cap_mask);
+		dma_cap_set(DMA_SG, echan->caps.cap_mask);
+		echan->caps.seg_nr = MAX_NR_SG;
 
 		vchan_init(&echan->vchan, dma);
 
@@ -538,6 +566,7 @@ static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma,
 	dma->device_alloc_chan_resources = edma_alloc_chan_resources;
 	dma->device_free_chan_resources = edma_free_chan_resources;
 	dma->device_issue_pending = edma_issue_pending;
+	dma->device_channel_caps = edma_get_channel_caps;
 	dma->device_tx_status = edma_tx_status;
 	dma->device_control = edma_control;
 	dma->dev = dev;
@@ -565,6 +594,7 @@ static int edma_probe(struct platform_device *pdev)
 
 	dma_cap_zero(ecc->dma_slave.cap_mask);
 	dma_cap_set(DMA_SLAVE, ecc->dma_slave.cap_mask);
+	dma_cap_set(DMA_PRIVATE, ecc->dma_slave.cap_mask);
 
 	edma_dma_init(ecc, &ecc->dma_slave, &pdev->dev);
 
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 682de75..6b5fc42 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -79,6 +79,20 @@ config GPIO_SYSFS
 	  Kernel drivers may also request that a particular GPIO be
 	  exported to userspace; this can be useful when debugging.
 
+config GPIO_OF_HELPER
+	bool "GPIO OF helper device"
+	depends on OF_GPIO && EXPERIMENTAL
+	help
+	  Say Y here to add an GPIO OF helper driver
+
+	  Allows you specify a GPIO helper based on OF
+	  which allows simple export of GPIO functionality
+	  in user-space.
+
+	  Features include, value set/get, direction control,
+	  interrupt/value change poll support, event counting
+	  and others.
+
 config GPIO_GENERIC
 	tristate
 
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index c5aebd0..126e2cb 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -5,6 +5,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
+obj-$(CONFIG_GPIO_OF_HELPER)	+= gpio-of-helper.o
 
 # Device drivers. Generally keep list sorted alphabetically
 obj-$(CONFIG_GPIO_GENERIC)	+= gpio-generic.o
diff --git a/drivers/gpio/gpio-of-helper.c b/drivers/gpio/gpio-of-helper.c
new file mode 100644
index 0000000..16a607f
--- /dev/null
+++ b/drivers/gpio/gpio-of-helper.c
@@ -0,0 +1,414 @@
+/*
+ * GPIO OF based helper
+ *
+ * A simple DT based driver to provide access to GPIO functionality
+ * to user-space via sysfs.
+ *
+ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/math64.h>
+#include <linux/atomic.h>
+#include <linux/idr.h>
+
+/* fwd decl. */
+struct gpio_of_helper_info;
+
+enum gpio_type {
+	GPIO_TYPE_INPUT = 0,
+	GPIO_TYPE_OUTPUT = 1,
+};
+
+struct gpio_of_entry {
+	int id;
+	struct gpio_of_helper_info *info;
+	struct device_node *node;
+	enum gpio_type type;
+	int gpio;
+	enum of_gpio_flags gpio_flags;
+	int irq;
+	const char *name;
+	atomic64_t counter;
+	unsigned int count_flags;
+#define COUNT_RISING_EDGE	(1 << 0)
+#define COUNT_FALLING_EDGE	(1 << 1)
+};
+
+struct gpio_of_helper_info {
+	struct platform_device *pdev;
+	struct idr idr;
+};
+
+static const struct of_device_id gpio_of_helper_of_match[] = {
+	{
+		.compatible = "gpio-of-helper",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, gpio_of_helper_of_match);
+
+static ssize_t gpio_of_helper_show_status(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_of_helper_info *info = platform_get_drvdata(pdev);
+	struct gpio_of_entry *entry;
+	char *p, *e;
+	int id, n;
+
+	p = buf;
+	e = p + PAGE_SIZE;
+	n = 0;
+	idr_for_each_entry(&info->idr, entry, id) {
+		switch (entry->type) {
+		case GPIO_TYPE_INPUT:
+			n = snprintf(p, e - p, "%2d %-24s %3d %-3s %llu\n",
+				entry->id, entry->name, entry->gpio, "IN",
+				(unsigned long long)
+					atomic64_read(&entry->counter));
+			break;
+		case GPIO_TYPE_OUTPUT:
+			n = snprintf(p, e - p, "%2d %-24s %3d %-3s\n",
+				entry->id, entry->name, entry->gpio, "OUT");
+			break;
+		}
+		p += n;
+	}
+
+	return p - buf;
+}
+
+static DEVICE_ATTR(status, S_IRUGO,
+		gpio_of_helper_show_status, NULL);
+
+static irqreturn_t gpio_of_helper_handler(int irq, void *ptr)
+{
+	struct gpio_of_entry *entry = ptr;
+
+	/* caution - low speed interfaces only! */
+	atomic64_inc(&entry->counter);
+
+	return IRQ_HANDLED;
+}
+
+static struct gpio_of_entry *
+gpio_of_entry_create(struct gpio_of_helper_info *info,
+		struct device_node *node)
+{
+	struct platform_device *pdev = info->pdev;
+	struct device *dev = &pdev->dev;
+	struct gpio_of_entry *entry;
+	int err, gpio, irq;
+	unsigned int req_flags, count_flags, irq_flags;
+	enum gpio_type type;
+	enum of_gpio_flags gpio_flags;
+	const char *name;
+
+	/* get the type of the node first */
+	if (of_property_read_bool(node, "input"))
+		type = GPIO_TYPE_INPUT;
+	else if (of_property_read_bool(node, "output"))
+		type = GPIO_TYPE_OUTPUT;
+	else {
+		dev_err(dev, "Not valid gpio node type\n");
+		err = -EINVAL;
+		goto err_bad_node;
+	}
+
+	/* get the name */
+	err = of_property_read_string(node, "gpio-name", &name);
+	if (err != 0) {
+		dev_err(dev, "Failed to get name property\n");
+		goto err_bad_node;
+	}
+
+	err = of_get_named_gpio_flags(node, "gpio", 0, &gpio_flags);
+	if (IS_ERR_VALUE(err)) {
+		dev_err(dev, "Failed to get gpio property of '%s'\n", name);
+		goto err_bad_node;
+	}
+	gpio = err;
+
+	req_flags = 0;
+	count_flags = 0;
+
+	/* set the request flags */
+	switch (type) {
+		case GPIO_TYPE_INPUT:
+			req_flags = GPIOF_DIR_IN | GPIOF_EXPORT;
+			if (of_property_read_bool(node, "count-falling-edge"))
+				count_flags |= COUNT_FALLING_EDGE;
+			if (of_property_read_bool(node, "count-rising-edge"))
+				count_flags |= COUNT_RISING_EDGE;
+			break;
+		case GPIO_TYPE_OUTPUT:
+			req_flags = GPIOF_DIR_OUT | GPIOF_EXPORT;
+			if (of_property_read_bool(node, "init-high"))
+				req_flags |= GPIOF_OUT_INIT_HIGH;
+			else if (of_property_read_bool(node, "init-low"))
+				req_flags |= GPIOF_OUT_INIT_LOW;
+			break;
+	}
+
+	/* request the gpio */
+	err = devm_gpio_request_one(dev, gpio, req_flags, name);
+	if (err != 0) {
+		dev_err(dev, "Failed to request gpio '%s'\n", name);
+		goto err_bad_node;
+	}
+
+	irq = -1;
+	irq_flags = 0;
+
+	/* counter mode requested - need an interrupt */
+	if (count_flags != 0) {
+		irq = gpio_to_irq(gpio);
+		if (IS_ERR_VALUE(irq)) {
+			dev_err(dev, "Failed to request gpio '%s'\n", name);
+			goto err_bad_node;
+		}
+
+		if (count_flags & COUNT_RISING_EDGE)
+			irq_flags |= IRQF_TRIGGER_RISING;
+		if (count_flags & COUNT_FALLING_EDGE)
+			irq_flags |= IRQF_TRIGGER_FALLING;
+	}
+
+	if (!idr_pre_get(&info->idr, GFP_KERNEL)) {
+		dev_err(dev, "Failed on idr_pre_get of '%s'\n", name);
+		err = -ENOMEM;
+		goto err_no_mem;
+	}
+
+	entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
+	if (entry == NULL) {
+		dev_err(dev, "Failed to allocate gpio entry of '%s'\n", name);
+		err = -ENOMEM;
+		goto err_no_mem;
+	}
+
+	entry->id = -1;
+	entry->info = info;
+	entry->node = of_node_get(node);	/* get node reference */
+	entry->type = type;
+	entry->gpio = gpio;
+	entry->gpio_flags = gpio_flags;
+	entry->irq = irq;
+	entry->name = name;
+
+	/* interrupt enable is last thing done */
+	if (irq >= 0) {
+		atomic64_set(&entry->counter, 0);
+		entry->count_flags = count_flags;
+		err = devm_request_irq(dev, irq, gpio_of_helper_handler,
+				irq_flags, name, entry);
+		if (err != 0) {
+			dev_err(dev, "Failed to request irq of '%s'\n", name);
+			goto err_no_irq;
+		}
+	}
+
+	/* all done; insert */
+	err = idr_get_new(&info->idr, entry, &entry->id);
+	if (IS_ERR_VALUE(err)) {
+		dev_err(dev, "Failed to idr_get_new  of '%s'\n", name);
+		goto err_fail_idr;
+	}
+
+	dev_info(dev, "Allocated GPIO id=%d\n", entry->id);
+
+	return entry;
+
+err_fail_idr:
+	/* nothing to do */
+err_no_irq:
+	/* release node ref */
+	of_node_put(node);
+	/* nothing else needs to be done, devres handles it */
+err_no_mem:
+err_bad_node:
+	return ERR_PTR(err);
+}
+
+static int gpio_of_entry_destroy(struct gpio_of_entry *entry)
+{
+	struct gpio_of_helper_info *info = entry->info;
+	struct platform_device *pdev = info->pdev;
+	struct device *dev = &pdev->dev;
+
+	dev_info(dev, "Destroying GPIO id=%d\n", entry->id);
+
+	/* remove from the IDR */
+	idr_remove(&info->idr, entry->id);
+
+	/* remove node ref */
+	of_node_put(entry->node);
+
+	/* free gpio */
+	devm_gpio_free(dev, entry->gpio);
+
+	/* gree irq */
+	if (entry->irq >= 0)
+		devm_free_irq(dev, entry->irq, entry);
+
+	/* and free */
+	devm_kfree(dev, entry);
+
+	return 0;
+}
+
+static int gpio_of_helper_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct gpio_of_helper_info *info;
+	struct gpio_of_entry *entry;
+	struct device_node *pnode = pdev->dev.of_node;
+	struct device_node *cnode;
+	struct pinctrl *pinctrl;
+	int err;
+
+	/* we only support OF */
+	if (pnode == NULL) {
+		dev_err(&pdev->dev, "No platform of_node!\n");
+		return -ENODEV;
+	}
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		/* special handling for probe defer */
+		if (PTR_ERR(pinctrl) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		dev_warn(&pdev->dev,
+			"pins are not configured from the driver\n");
+	}
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (info == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate info\n");
+		err = -ENOMEM;
+		goto err_no_mem;
+	}
+	platform_set_drvdata(pdev, info);
+	info->pdev = pdev;
+
+	idr_init(&info->idr);
+
+	err = device_create_file(dev, &dev_attr_status);
+	if (err != 0) {
+		dev_err(dev, "Failed to create status sysfs attribute\n");
+		goto err_no_sysfs;
+	}
+
+	for_each_child_of_node(pnode, cnode) {
+
+		entry = gpio_of_entry_create(info, cnode);
+		if (IS_ERR_OR_NULL(entry)) {
+			dev_err(dev, "Failed to create gpio entry\n");
+			err = PTR_ERR(entry);
+			goto err_fail_entry;
+		}
+	}
+
+	dev_info(&pdev->dev, "ready\n");
+
+	return 0;
+err_fail_entry:
+	device_remove_file(&pdev->dev, &dev_attr_status);
+err_no_sysfs:
+err_no_mem:
+	return err;
+}
+
+static int gpio_of_helper_remove(struct platform_device *pdev)
+{
+	struct gpio_of_helper_info *info = platform_get_drvdata(pdev);
+	struct gpio_of_entry *entry;
+	int id;
+
+	dev_info(&pdev->dev, "removing\n");
+
+	device_remove_file(&pdev->dev, &dev_attr_status);
+
+	id = 0;
+	idr_for_each_entry(&info->idr, entry, id) {
+		/* destroy each and every one */
+		gpio_of_entry_destroy(entry);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
+static int gpio_of_helper_runtime_suspend(struct device *dev)
+{
+	/* place holder */
+	return 0;
+}
+
+static int gpio_of_helper_runtime_resume(struct device *dev)
+{
+	/* place holder */
+	return 0;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+static struct dev_pm_ops gpio_of_helper_pm_ops = {
+	SET_RUNTIME_PM_OPS(gpio_of_helper_runtime_suspend,
+			   gpio_of_helper_runtime_resume, NULL)
+};
+#define GPIO_OF_HELPER_PM_OPS (&gpio_of_helper_pm_ops)
+#else
+#define GPIO_OF_HELPER_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+struct platform_driver gpio_of_helper_driver = {
+	.probe		= gpio_of_helper_probe,
+	.remove		= gpio_of_helper_remove,
+	.driver = {
+		.name		= "gpio-of-helper",
+		.owner		= THIS_MODULE,
+		.pm		= GPIO_OF_HELPER_PM_OPS,
+		.of_match_table	= gpio_of_helper_of_match,
+	},
+};
+
+module_platform_driver(gpio_of_helper_driver);
+
+MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
+MODULE_DESCRIPTION("GPIO OF Helper driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-of-helper");
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 983201b..6c322d6 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -69,6 +69,8 @@ config DRM_KMS_CMA_HELPER
 	help
 	  Choose this if you need the KMS CMA helper functions
 
+source "drivers/gpu/drm/i2c/Kconfig"
+
 config DRM_TDFX
 	tristate "3dfx Banshee/Voodoo3+"
 	depends on DRM && PCI
@@ -212,3 +214,5 @@ source "drivers/gpu/drm/cirrus/Kconfig"
 source "drivers/gpu/drm/shmobile/Kconfig"
 
 source "drivers/gpu/drm/tegra/Kconfig"
+
+source "drivers/gpu/drm/tilcdc/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 6f58c81..3af934d 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -50,4 +50,5 @@ obj-$(CONFIG_DRM_UDL) += udl/
 obj-$(CONFIG_DRM_AST) += ast/
 obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
 obj-$(CONFIG_DRM_TEGRA) += tegra/
+obj-$(CONFIG_DRM_TILCDC)	+= tilcdc/
 obj-y			+= i2c/
diff --git a/drivers/gpu/drm/drm_encoder_slave.c b/drivers/gpu/drm/drm_encoder_slave.c
index 63e7334..48c52f7 100644
--- a/drivers/gpu/drm/drm_encoder_slave.c
+++ b/drivers/gpu/drm/drm_encoder_slave.c
@@ -123,3 +123,66 @@ void drm_i2c_encoder_destroy(struct drm_encoder *drm_encoder)
 	module_put(module);
 }
 EXPORT_SYMBOL(drm_i2c_encoder_destroy);
+
+/*
+ * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs:
+ */
+
+static inline struct drm_encoder_slave_funcs *
+get_slave_funcs(struct drm_encoder *enc)
+{
+	return to_encoder_slave(enc)->slave_funcs;
+}
+
+void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	get_slave_funcs(encoder)->dpms(encoder, mode);
+}
+EXPORT_SYMBOL(drm_i2c_encoder_dpms);
+
+bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder,
+		const struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	return get_slave_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode);
+}
+EXPORT_SYMBOL(drm_i2c_encoder_mode_fixup);
+
+void drm_i2c_encoder_prepare(struct drm_encoder *encoder)
+{
+	drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+EXPORT_SYMBOL(drm_i2c_encoder_prepare);
+
+void drm_i2c_encoder_commit(struct drm_encoder *encoder)
+{
+	drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+EXPORT_SYMBOL(drm_i2c_encoder_commit);
+
+void drm_i2c_encoder_mode_set(struct drm_encoder *encoder,
+		struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode);
+}
+EXPORT_SYMBOL(drm_i2c_encoder_mode_set);
+
+enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder,
+	    struct drm_connector *connector)
+{
+	return get_slave_funcs(encoder)->detect(encoder, connector);
+}
+EXPORT_SYMBOL(drm_i2c_encoder_detect);
+
+void drm_i2c_encoder_save(struct drm_encoder *encoder)
+{
+	get_slave_funcs(encoder)->save(encoder);
+}
+EXPORT_SYMBOL(drm_i2c_encoder_save);
+
+void drm_i2c_encoder_restore(struct drm_encoder *encoder)
+{
+	get_slave_funcs(encoder)->restore(encoder);
+}
+EXPORT_SYMBOL(drm_i2c_encoder_restore);
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index fd9d0af..18866ee 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -180,6 +180,59 @@ struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
 }
 EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
 
+#ifdef CONFIG_DEBUG_FS
+/**
+ * drm_fb_cma_describe() - Helper to dump information about a single
+ * CMA framebuffer object
+ */
+void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m)
+{
+	struct drm_fb_cma *fb_cma = to_fb_cma(fb);
+	int i, n = drm_format_num_planes(fb->pixel_format);
+
+	seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
+			(char *)&fb->pixel_format);
+
+	for (i = 0; i < n; i++) {
+		seq_printf(m, "   %d: offset=%d pitch=%d, obj: ",
+				i, fb->offsets[i], fb->pitches[i]);
+		drm_gem_cma_describe(fb_cma->obj[i], m);
+	}
+}
+EXPORT_SYMBOL_GPL(drm_fb_cma_describe);
+
+/**
+ * drm_fb_cma_debugfs_show() - Helper to list CMA framebuffer objects
+ * in debugfs.
+ */
+int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_framebuffer *fb;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+	if (ret)
+		return ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret) {
+		mutex_unlock(&dev->mode_config.mutex);
+		return ret;
+	}
+
+	list_for_each_entry(fb, &dev->mode_config.fb_list, head)
+		drm_fb_cma_describe(fb, m);
+
+	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(drm_fb_cma_debugfs_show);
+#endif
+
 static struct fb_ops drm_fbdev_cma_ops = {
 	.owner		= THIS_MODULE,
 	.fb_fillrect	= sys_fillrect,
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
index 1aa8fee..0a7e011 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -249,3 +249,24 @@ int drm_gem_cma_dumb_destroy(struct drm_file *file_priv,
 	return drm_gem_handle_delete(file_priv, handle);
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_destroy);
+
+#ifdef CONFIG_DEBUG_FS
+void drm_gem_cma_describe(struct drm_gem_cma_object *cma_obj, struct seq_file *m)
+{
+	struct drm_gem_object *obj = &cma_obj->base;
+	struct drm_device *dev = obj->dev;
+	uint64_t off = 0;
+
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	if (obj->map_list.map)
+		off = (uint64_t)obj->map_list.hash.key;
+
+	seq_printf(m, "%2d (%2d) %08llx %08Zx %p %d",
+			obj->name, obj->refcount.refcount.counter,
+			off, cma_obj->paddr, cma_obj->vaddr, obj->size);
+
+	seq_printf(m, "\n");
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_describe);
+#endif
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 19c01ca..9bb83a5 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -863,6 +863,7 @@ void drm_send_vblank_event(struct drm_device *dev, int crtc,
 
 		now = get_drm_timestamp();
 	}
+	e->pipe = crtc;
 	send_vblank_event(dev, e, seq, &now);
 }
 EXPORT_SYMBOL(drm_send_vblank_event);
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index d8da30e..04fa6f1 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -35,6 +35,8 @@
 #include <linux/export.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
 
 /**
  * drm_mode_debug_printmodeline - debug print a mode
@@ -504,6 +506,74 @@ drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
 }
 EXPORT_SYMBOL(drm_gtf_mode);
 
+#if IS_ENABLED(CONFIG_VIDEOMODE)
+int drm_display_mode_from_videomode(const struct videomode *vm,
+				    struct drm_display_mode *dmode)
+{
+	dmode->hdisplay = vm->hactive;
+	dmode->hsync_start = dmode->hdisplay + vm->hfront_porch;
+	dmode->hsync_end = dmode->hsync_start + vm->hsync_len;
+	dmode->htotal = dmode->hsync_end + vm->hback_porch;
+
+	dmode->vdisplay = vm->vactive;
+	dmode->vsync_start = dmode->vdisplay + vm->vfront_porch;
+	dmode->vsync_end = dmode->vsync_start + vm->vsync_len;
+	dmode->vtotal = dmode->vsync_end + vm->vback_porch;
+
+	dmode->clock = vm->pixelclock / 1000;
+
+	dmode->flags = 0;
+	if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
+		dmode->flags |= DRM_MODE_FLAG_PHSYNC;
+	else if (vm->dmt_flags & VESA_DMT_HSYNC_LOW)
+		dmode->flags |= DRM_MODE_FLAG_NHSYNC;
+	if (vm->dmt_flags & VESA_DMT_VSYNC_HIGH)
+		dmode->flags |= DRM_MODE_FLAG_PVSYNC;
+	else if (vm->dmt_flags & VESA_DMT_VSYNC_LOW)
+		dmode->flags |= DRM_MODE_FLAG_NVSYNC;
+	if (vm->data_flags & DISPLAY_FLAGS_INTERLACED)
+		dmode->flags |= DRM_MODE_FLAG_INTERLACE;
+	if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN)
+		dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
+	drm_mode_set_name(dmode);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
+#endif
+
+#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+/**
+ * of_get_drm_display_mode - get a drm_display_mode from devicetree
+ * @np: device_node with the timing specification
+ * @dmode: will be set to the return value
+ * @index: index into the list of display timings in devicetree
+ *
+ * This function is expensive and should only be used, if only one mode is to be
+ * read from DT. To get multiple modes start with of_get_display_timings and
+ * work with that instead.
+ */
+int of_get_drm_display_mode(struct device_node *np,
+			    struct drm_display_mode *dmode, int index)
+{
+	struct videomode vm;
+	int ret;
+
+	ret = of_get_videomode(np, &vm, index);
+	if (ret)
+		return ret;
+
+	drm_display_mode_from_videomode(&vm, dmode);
+
+	pr_debug("%s: got %dx%d display mode from %s\n",
+		of_node_full_name(np), vm.hactive, vm.vactive, np->name);
+	drm_mode_debug_printmodeline(dmode);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
+#endif
+
 /**
  * drm_mode_set_name - set the name on a mode
  * @mode: name will be set in this mode
diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
new file mode 100644
index 0000000..2342005
--- /dev/null
+++ b/drivers/gpu/drm/i2c/Kconfig
@@ -0,0 +1,29 @@
+menu "I2C encoder or helper chips"
+     depends on DRM && DRM_KMS_HELPER && I2C
+
+config DRM_I2C_CH7006
+	tristate "Chrontel ch7006 TV encoder"
+	default m if DRM_NOUVEAU
+	help
+	  Support for Chrontel ch7006 and similar TV encoders, found
+	  on some nVidia video cards.
+
+	  This driver is currently only useful if you're also using
+	  the nouveau driver.
+
+config DRM_I2C_SIL164
+	tristate "Silicon Image sil164 TMDS transmitter"
+	default m if DRM_NOUVEAU
+	help
+	  Support for sil164 and similar single-link (or dual-link
+	  when used in pairs) TMDS transmitters, used in some nVidia
+	  video cards.
+
+config DRM_I2C_NXP_TDA998X
+	tristate "NXP Semiconductors TDA998X HDMI encoder"
+	default m if DRM_TILCDC
+	select HDMI
+	help
+	  Support for NXP Semiconductors TDA998X HDMI encoders.
+
+endmenu
diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile
index 9286256..0ba6bd3 100644
--- a/drivers/gpu/drm/i2c/Makefile
+++ b/drivers/gpu/drm/i2c/Makefile
@@ -5,3 +5,6 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
 
 sil164-y := sil164_drv.o
 obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o
+
+tda998x-y := tda998x_drv.o tda998x_audio_drv.o
+obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o
diff --git a/drivers/gpu/drm/i2c/tda998x_audio_drv.c b/drivers/gpu/drm/i2c/tda998x_audio_drv.c
new file mode 100644
index 0000000..c13e25b
--- /dev/null
+++ b/drivers/gpu/drm/i2c/tda998x_audio_drv.c
@@ -0,0 +1,76 @@
+/*
+ * ALSA SoC codec driver for HDMI audio on NXP TDA998x series.
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Darren Etheridge <detheridge@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/module.h>
+#include <sound/soc.h>
+#include <linux/of_device.h>
+
+#define DRV_NAME "nxp-hdmi-audio-codec"
+
+static struct snd_soc_codec_driver nxp_hdmi_codec;
+
+static struct snd_soc_dai_driver nxp_hdmi_codec_dai = {
+	.name = "nxp-hdmi-hifi",
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S32_LE,
+	},
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id nxptda_dt_ids[] = {
+        { .compatible = "nxp,nxptda", },
+        { }
+};
+MODULE_DEVICE_TABLE(of, nxptda_dt_ids);
+#endif
+
+
+static int nxp_hdmi_codec_probe(struct platform_device *pdev)
+{
+	return snd_soc_register_codec(&pdev->dev, &nxp_hdmi_codec,
+			&nxp_hdmi_codec_dai, 1);
+}
+
+static int nxp_hdmi_codec_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver nxp_hdmi_codec_driver = {
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(nxptda_dt_ids)
+	},
+
+	.probe		= nxp_hdmi_codec_probe,
+	.remove		= nxp_hdmi_codec_remove,
+};
+
+module_platform_driver(nxp_hdmi_codec_driver);
+
+MODULE_AUTHOR("Darren Etheridge <detheridge@ti.com>");
+MODULE_DESCRIPTION("ASoC NXP Dummy HDMI codec driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
new file mode 100644
index 0000000..412ba4f
--- /dev/null
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -0,0 +1,1099 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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 <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_edid.h>
+#include <linux/hdmi.h>
+
+#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+
+struct tda998x_priv {
+	struct i2c_client *cec;
+	uint16_t rev;
+	uint8_t current_page;
+	int dpms;
+};
+
+#define to_tda998x_priv(x)  ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
+
+/* The TDA9988 series of devices use a paged register scheme.. to simplify
+ * things we encode the page # in upper bits of the register #.  To read/
+ * write a given register, we need to make sure CURPAGE register is set
+ * appropriately.  Which implies reads/writes are not atomic.  Fun!
+ */
+
+#define REG(page, addr) (((page) << 8) | (addr))
+#define REG2ADDR(reg)   ((reg) & 0xff)
+#define REG2PAGE(reg)   (((reg) >> 8) & 0xff)
+
+#define REG_CURPAGE               0xff                /* write */
+
+
+/* Page 00h: General Control */
+#define REG_VERSION_LSB           REG(0x00, 0x00)     /* read */
+#define REG_MAIN_CNTRL0           REG(0x00, 0x01)     /* read/write */
+# define MAIN_CNTRL0_SR           (1 << 0)
+# define MAIN_CNTRL0_DECS         (1 << 1)
+# define MAIN_CNTRL0_DEHS         (1 << 2)
+# define MAIN_CNTRL0_CECS         (1 << 3)
+# define MAIN_CNTRL0_CEHS         (1 << 4)
+# define MAIN_CNTRL0_SCALER       (1 << 7)
+#define REG_VERSION_MSB           REG(0x00, 0x02)     /* read */
+#define REG_SOFTRESET             REG(0x00, 0x0a)     /* write */
+# define SOFTRESET_AUDIO          (1 << 0)
+# define SOFTRESET_I2C_MASTER     (1 << 1)
+#define REG_DDC_DISABLE           REG(0x00, 0x0b)     /* read/write */
+#define REG_CCLK_ON               REG(0x00, 0x0c)     /* read/write */
+#define REG_I2C_MASTER            REG(0x00, 0x0d)     /* read/write */
+# define I2C_MASTER_DIS_MM        (1 << 0)
+# define I2C_MASTER_DIS_FILT      (1 << 1)
+# define I2C_MASTER_APP_STRT_LAT  (1 << 2)
+#define REG_INT_FLAGS_0           REG(0x00, 0x0f)     /* read/write */
+#define REG_INT_FLAGS_1           REG(0x00, 0x10)     /* read/write */
+#define REG_INT_FLAGS_2           REG(0x00, 0x11)     /* read/write */
+# define INT_FLAGS_2_EDID_BLK_RD  (1 << 1)
+#define REG_ENA_VP_0              REG(0x00, 0x18)     /* read/write */
+#define REG_ENA_VP_1              REG(0x00, 0x19)     /* read/write */
+#define REG_ENA_VP_2              REG(0x00, 0x1a)     /* read/write */
+#define REG_ENA_AP                REG(0x00, 0x1e)     /* read/write */
+#define REG_VIP_CNTRL_0           REG(0x00, 0x20)     /* write */
+# define VIP_CNTRL_0_MIRR_A       (1 << 7)
+# define VIP_CNTRL_0_SWAP_A(x)    (((x) & 7) << 4)
+# define VIP_CNTRL_0_MIRR_B       (1 << 3)
+# define VIP_CNTRL_0_SWAP_B(x)    (((x) & 7) << 0)
+#define REG_VIP_CNTRL_1           REG(0x00, 0x21)     /* write */
+# define VIP_CNTRL_1_MIRR_C       (1 << 7)
+# define VIP_CNTRL_1_SWAP_C(x)    (((x) & 7) << 4)
+# define VIP_CNTRL_1_MIRR_D       (1 << 3)
+# define VIP_CNTRL_1_SWAP_D(x)    (((x) & 7) << 0)
+#define REG_VIP_CNTRL_2           REG(0x00, 0x22)     /* write */
+# define VIP_CNTRL_2_MIRR_E       (1 << 7)
+# define VIP_CNTRL_2_SWAP_E(x)    (((x) & 7) << 4)
+# define VIP_CNTRL_2_MIRR_F       (1 << 3)
+# define VIP_CNTRL_2_SWAP_F(x)    (((x) & 7) << 0)
+#define REG_VIP_CNTRL_3           REG(0x00, 0x23)     /* write */
+# define VIP_CNTRL_3_X_TGL        (1 << 0)
+# define VIP_CNTRL_3_H_TGL        (1 << 1)
+# define VIP_CNTRL_3_V_TGL        (1 << 2)
+# define VIP_CNTRL_3_EMB          (1 << 3)
+# define VIP_CNTRL_3_SYNC_DE      (1 << 4)
+# define VIP_CNTRL_3_SYNC_HS      (1 << 5)
+# define VIP_CNTRL_3_DE_INT       (1 << 6)
+# define VIP_CNTRL_3_EDGE         (1 << 7)
+#define REG_VIP_CNTRL_4           REG(0x00, 0x24)     /* write */
+# define VIP_CNTRL_4_BLC(x)       (((x) & 3) << 0)
+# define VIP_CNTRL_4_BLANKIT(x)   (((x) & 3) << 2)
+# define VIP_CNTRL_4_CCIR656      (1 << 4)
+# define VIP_CNTRL_4_656_ALT      (1 << 5)
+# define VIP_CNTRL_4_TST_656      (1 << 6)
+# define VIP_CNTRL_4_TST_PAT      (1 << 7)
+#define REG_VIP_CNTRL_5           REG(0x00, 0x25)     /* write */
+# define VIP_CNTRL_5_CKCASE       (1 << 0)
+# define VIP_CNTRL_5_SP_CNT(x)    (((x) & 3) << 1)
+
+#define REG_MUX_AP                REG(0x00, 0x26)
+# define MUX_AP_SELECT_I2S        (0x64)
+#define REG_MAT_CONTRL            REG(0x00, 0x80)     /* write */
+# define MAT_CONTRL_MAT_SC(x)     (((x) & 3) << 0)
+# define MAT_CONTRL_MAT_BP        (1 << 2)
+#define REG_VIDFORMAT             REG(0x00, 0xa0)     /* write */
+#define REG_REFPIX_MSB            REG(0x00, 0xa1)     /* write */
+#define REG_REFPIX_LSB            REG(0x00, 0xa2)     /* write */
+#define REG_REFLINE_MSB           REG(0x00, 0xa3)     /* write */
+#define REG_REFLINE_LSB           REG(0x00, 0xa4)     /* write */
+#define REG_NPIX_MSB              REG(0x00, 0xa5)     /* write */
+#define REG_NPIX_LSB              REG(0x00, 0xa6)     /* write */
+#define REG_NLINE_MSB             REG(0x00, 0xa7)     /* write */
+#define REG_NLINE_LSB             REG(0x00, 0xa8)     /* write */
+#define REG_VS_LINE_STRT_1_MSB    REG(0x00, 0xa9)     /* write */
+#define REG_VS_LINE_STRT_1_LSB    REG(0x00, 0xaa)     /* write */
+#define REG_VS_PIX_STRT_1_MSB     REG(0x00, 0xab)     /* write */
+#define REG_VS_PIX_STRT_1_LSB     REG(0x00, 0xac)     /* write */
+#define REG_VS_LINE_END_1_MSB     REG(0x00, 0xad)     /* write */
+#define REG_VS_LINE_END_1_LSB     REG(0x00, 0xae)     /* write */
+#define REG_VS_PIX_END_1_MSB      REG(0x00, 0xaf)     /* write */
+#define REG_VS_PIX_END_1_LSB      REG(0x00, 0xb0)     /* write */
+#define REG_VS_PIX_STRT_2_MSB     REG(0x00, 0xb3)     /* write */
+#define REG_VS_PIX_STRT_2_LSB     REG(0x00, 0xb4)     /* write */
+#define REG_VS_PIX_END_2_MSB      REG(0x00, 0xb7)     /* write */
+#define REG_VS_PIX_END_2_LSB      REG(0x00, 0xb8)     /* write */
+#define REG_HS_PIX_START_MSB      REG(0x00, 0xb9)     /* write */
+#define REG_HS_PIX_START_LSB      REG(0x00, 0xba)     /* write */
+#define REG_HS_PIX_STOP_MSB       REG(0x00, 0xbb)     /* write */
+#define REG_HS_PIX_STOP_LSB       REG(0x00, 0xbc)     /* write */
+#define REG_VWIN_START_1_MSB      REG(0x00, 0xbd)     /* write */
+#define REG_VWIN_START_1_LSB      REG(0x00, 0xbe)     /* write */
+#define REG_VWIN_END_1_MSB        REG(0x00, 0xbf)     /* write */
+#define REG_VWIN_END_1_LSB        REG(0x00, 0xc0)     /* write */
+#define REG_DE_START_MSB          REG(0x00, 0xc5)     /* write */
+#define REG_DE_START_LSB          REG(0x00, 0xc6)     /* write */
+#define REG_DE_STOP_MSB           REG(0x00, 0xc7)     /* write */
+#define REG_DE_STOP_LSB           REG(0x00, 0xc8)     /* write */
+#define REG_TBG_CNTRL_0           REG(0x00, 0xca)     /* write */
+# define TBG_CNTRL_0_FRAME_DIS    (1 << 5)
+# define TBG_CNTRL_0_SYNC_MTHD    (1 << 6)
+# define TBG_CNTRL_0_SYNC_ONCE    (1 << 7)
+#define REG_TBG_CNTRL_1           REG(0x00, 0xcb)     /* write */
+# define TBG_CNTRL_1_VH_TGL_0     (1 << 0)
+# define TBG_CNTRL_1_VH_TGL_1     (1 << 1)
+# define TBG_CNTRL_1_VH_TGL_2     (1 << 2)
+# define TBG_CNTRL_1_VHX_EXT_DE   (1 << 3)
+# define TBG_CNTRL_1_VHX_EXT_HS   (1 << 4)
+# define TBG_CNTRL_1_VHX_EXT_VS   (1 << 5)
+# define TBG_CNTRL_1_DWIN_DIS     (1 << 6)
+#define REG_ENABLE_SPACE          REG(0x00, 0xd6)     /* write */
+#define REG_HVF_CNTRL_0           REG(0x00, 0xe4)     /* write */
+# define HVF_CNTRL_0_SM           (1 << 7)
+# define HVF_CNTRL_0_RWB          (1 << 6)
+# define HVF_CNTRL_0_PREFIL(x)    (((x) & 3) << 2)
+# define HVF_CNTRL_0_INTPOL(x)    (((x) & 3) << 0)
+#define REG_HVF_CNTRL_1           REG(0x00, 0xe5)     /* write */
+# define HVF_CNTRL_1_FOR          (1 << 0)
+# define HVF_CNTRL_1_YUVBLK       (1 << 1)
+# define HVF_CNTRL_1_VQR(x)       (((x) & 3) << 2)
+# define HVF_CNTRL_1_PAD(x)       (((x) & 3) << 4)
+# define HVF_CNTRL_1_SEMI_PLANAR  (1 << 6)
+#define REG_RPT_CNTRL             REG(0x00, 0xf0)     /* write */
+#define REG_I2S_FORMAT            REG(0x00, 0xfc)
+
+#define REG_AIP_CLKSEL            REG(0x00, 0xfd)
+# define SEL_AIP_I2S              (1 << 3)  /* I2S Clk */
+
+/* Page 02h: PLL settings */
+#define REG_PLL_SERIAL_1          REG(0x02, 0x00)     /* read/write */
+# define PLL_SERIAL_1_SRL_FDN     (1 << 0)
+# define PLL_SERIAL_1_SRL_IZ(x)   (((x) & 3) << 1)
+# define PLL_SERIAL_1_SRL_MAN_IZ  (1 << 6)
+#define REG_PLL_SERIAL_2          REG(0x02, 0x01)     /* read/write */
+# define PLL_SERIAL_2_SRL_NOSC(x) (((x) & 3) << 0)
+# define PLL_SERIAL_2_SRL_PR(x)   (((x) & 0xf) << 4)
+#define REG_PLL_SERIAL_3          REG(0x02, 0x02)     /* read/write */
+# define PLL_SERIAL_3_SRL_CCIR    (1 << 0)
+# define PLL_SERIAL_3_SRL_DE      (1 << 2)
+# define PLL_SERIAL_3_SRL_PXIN_SEL (1 << 4)
+#define REG_SERIALIZER            REG(0x02, 0x03)     /* read/write */
+#define REG_BUFFER_OUT            REG(0x02, 0x04)     /* read/write */
+#define REG_PLL_SCG1              REG(0x02, 0x05)     /* read/write */
+#define REG_PLL_SCG2              REG(0x02, 0x06)     /* read/write */
+#define REG_PLL_SCGN1             REG(0x02, 0x07)     /* read/write */
+#define REG_PLL_SCGN2             REG(0x02, 0x08)     /* read/write */
+#define REG_PLL_SCGR1             REG(0x02, 0x09)     /* read/write */
+#define REG_PLL_SCGR2             REG(0x02, 0x0a)     /* read/write */
+#define REG_AUDIO_DIV             REG(0x02, 0x0e)     /* read/write */
+#define REG_SEL_CLK               REG(0x02, 0x11)     /* read/write */
+# define SEL_CLK_SEL_CLK1         (1 << 0)
+# define SEL_CLK_SEL_VRF_CLK(x)   (((x) & 3) << 1)
+# define SEL_CLK_ENA_SC_CLK       (1 << 3)
+#define REG_ANA_GENERAL           REG(0x02, 0x12)     /* read/write */
+
+
+/* Page 09h: EDID Control */
+#define REG_EDID_DATA_0           REG(0x09, 0x00)     /* read */
+/* next 127 successive registers are the EDID block */
+#define REG_EDID_CTRL             REG(0x09, 0xfa)     /* read/write */
+#define REG_DDC_ADDR              REG(0x09, 0xfb)     /* read/write */
+#define REG_DDC_OFFS              REG(0x09, 0xfc)     /* read/write */
+#define REG_DDC_SEGM_ADDR         REG(0x09, 0xfd)     /* read/write */
+#define REG_DDC_SEGM              REG(0x09, 0xfe)     /* read/write */
+
+
+/* Page 10h: information frames and packets */
+#define REG_AVI_IF                REG(0x10, 0x40)   /* AVI Infoframe packet */
+#define REG_AUDIO_IF              REG(0x10, 0x80)   /* AVI Infoframe packet */
+
+/* Page 11h: audio settings and content info packets */
+#define REG_AIP_CNTRL_0           REG(0x11, 0x00)     /* read/write */
+# define AIP_CNTRL_0_RST_FIFO     (1 << 0)
+# define AIP_CNTRL_0_SWAP         (1 << 1)
+# define AIP_CNTRL_0_LAYOUT       (1 << 2)
+# define AIP_CNTRL_0_ACR_MAN      (1 << 5)
+# define AIP_CNTRL_0_RST_CTS      (1 << 6)
+#define REG_ACR_CTS_0             REG(0x11, 0x05)
+#define REG_ACR_CTS_1             REG(0x11, 0x06)
+#define REG_ACR_CTS_2             REG(0x11, 0x07)
+#define REG_ACR_N_0               REG(0x11, 0x08)
+#define REG_ACR_N_1               REG(0x11, 0x09)
+#define REG_ACR_N_2               REG(0x11, 0x0a)
+#define REG_GC_AVMUTE             REG(0x11, 0x0b)
+# define GC_AVMUTE_CLRMUTE        (1 << 0)
+# define GC_AVMUTE_SETMUTE        (1 << 1)
+#define REG_CTS_N                 REG(0x11, 0x0c)
+#define REG_ENC_CNTRL             REG(0x11, 0x0d)     /* read/write */
+# define ENC_CNTRL_RST_ENC        (1 << 0)
+# define ENC_CNTRL_RST_SEL        (1 << 1)
+# define ENC_CNTRL_CTL_CODE(x)    (((x) & 3) << 2)
+#define REG_DIP_FLAGS             REG(0x11, 0x0e)
+# define DIP_FLAGS_ACR            (1 << 0)
+#define REG_DIP_IF_FLAGS          REG(0x11, 0x0f)     /* read/write */
+#define DIP_IF_FLAGS_IF1          (1 << 1)
+#define DIP_IF_FLAGS_IF2          (1 << 2)
+#define DIP_IF_FLAGS_IF3          (1 << 3)
+#define DIP_IF_FLAGS_IF4          (1 << 4)
+#define DIP_IF_FLAGS_IF5          (1 << 5)
+
+/* Page 12h: HDCP and OTP */
+#define REG_TX3                   REG(0x12, 0x9a)     /* read/write */
+#define REG_TX33                  REG(0x12, 0xb8)     /* read/write */
+# define TX33_HDMI                (1 << 1)
+
+
+/* Page 13h: Gamut related metadata packets */
+
+
+
+/* CEC registers: (not paged)
+ */
+#define REG_CEC_FRO_IM_CLK_CTRL   0xfb                /* read/write */
+# define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7)
+# define CEC_FRO_IM_CLK_CTRL_ENA_OTP   (1 << 6)
+# define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1)
+# define CEC_FRO_IM_CLK_CTRL_FRO_DIV   (1 << 0)
+#define REG_CEC_RXSHPDLEV         0xfe                /* read */
+# define CEC_RXSHPDLEV_RXSENS     (1 << 0)
+# define CEC_RXSHPDLEV_HPD        (1 << 1)
+
+#define REG_CEC_ENAMODS           0xff                /* read/write */
+# define CEC_ENAMODS_DIS_FRO      (1 << 6)
+# define CEC_ENAMODS_DIS_CCLK     (1 << 5)
+# define CEC_ENAMODS_EN_RXSENS    (1 << 2)
+# define CEC_ENAMODS_EN_HDMI      (1 << 1)
+# define CEC_ENAMODS_EN_CEC       (1 << 0)
+
+
+/* Device versions: */
+#define TDA9989N2                 0x0101
+#define TDA19989                  0x0201
+#define TDA19989N2                0x0202
+#define TDA19988                  0x0301
+
+static uint8_t *
+do_get_edid(struct drm_encoder *encoder);
+
+static void
+cec_write(struct drm_encoder *encoder, uint16_t addr, uint8_t val)
+{
+	struct i2c_client *client = to_tda998x_priv(encoder)->cec;
+	uint8_t buf[] = {addr, val};
+	int ret;
+
+	ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
+	if (ret < 0)
+		dev_err(&client->dev, "Error %d writing to cec:0x%x\n", ret, addr);
+}
+
+static uint8_t
+cec_read(struct drm_encoder *encoder, uint8_t addr)
+{
+	struct i2c_client *client = to_tda998x_priv(encoder)->cec;
+	uint8_t val;
+	int ret;
+
+	ret = i2c_master_send(client, &addr, sizeof(addr));
+	if (ret < 0)
+		goto fail;
+
+	ret = i2c_master_recv(client, &val, sizeof(val));
+	if (ret < 0)
+		goto fail;
+
+	return val;
+
+fail:
+	dev_err(&client->dev, "Error %d reading from cec:0x%x\n", ret, addr);
+	return 0;
+}
+
+static void
+set_page(struct drm_encoder *encoder, uint16_t reg)
+{
+	struct tda998x_priv *priv = to_tda998x_priv(encoder);
+
+	if (REG2PAGE(reg) != priv->current_page) {
+		struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+		uint8_t buf[] = {
+				REG_CURPAGE, REG2PAGE(reg)
+		};
+		int ret = i2c_master_send(client, buf, sizeof(buf));
+		if (ret < 0)
+			dev_err(&client->dev, "Error %d writing to REG_CURPAGE\n", ret);
+
+		priv->current_page = REG2PAGE(reg);
+	}
+}
+
+static int
+reg_read_range(struct drm_encoder *encoder, uint16_t reg, char *buf, int cnt)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	uint8_t addr = REG2ADDR(reg);
+	int ret;
+
+	set_page(encoder, reg);
+
+	ret = i2c_master_send(client, &addr, sizeof(addr));
+	if (ret < 0)
+		goto fail;
+
+	ret = i2c_master_recv(client, buf, cnt);
+	if (ret < 0)
+		goto fail;
+
+	return ret;
+
+fail:
+	dev_err(&client->dev, "Error %d reading from 0x%x\n", ret, reg);
+	return ret;
+}
+
+static int
+reg_write_range(struct drm_encoder *encoder, uint16_t reg, char *buf, int cnt)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	int ret = 0;
+	uint8_t *i2cpacket;
+
+	i2cpacket = (uint8_t *)kmalloc(cnt + 1, GFP_KERNEL);
+	if(!i2cpacket) {
+		goto fail;
+	}
+	i2cpacket[0] = REG2ADDR(reg);
+	memcpy(&i2cpacket[1], buf, cnt);
+	
+	set_page(encoder, reg);
+
+	ret = i2c_master_send(client, i2cpacket, cnt+1);
+	kfree(i2cpacket);
+	if (ret < 0)
+		goto fail;
+
+	return ret;
+
+fail:
+	dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
+	return ret;
+}
+
+
+static uint8_t
+reg_read(struct drm_encoder *encoder, uint16_t reg)
+{
+	uint8_t val = 0;
+	reg_read_range(encoder, reg, &val, sizeof(val));
+	return val;
+}
+
+static void
+reg_write(struct drm_encoder *encoder, uint16_t reg, uint8_t val)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	uint8_t buf[] = {REG2ADDR(reg), val};
+	int ret;
+
+	set_page(encoder, reg);
+
+	ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
+	if (ret < 0)
+		dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
+}
+
+static void
+reg_write16(struct drm_encoder *encoder, uint16_t reg, uint16_t val)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+	uint8_t buf[] = {REG2ADDR(reg), val >> 8, val};
+	int ret;
+
+	set_page(encoder, reg);
+
+	ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
+	if (ret < 0)
+		dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
+}
+
+static void
+reg_set(struct drm_encoder *encoder, uint16_t reg, uint8_t val)
+{
+	reg_write(encoder, reg, reg_read(encoder, reg) | val);
+}
+
+static void
+reg_clear(struct drm_encoder *encoder, uint16_t reg, uint8_t val)
+{
+	reg_write(encoder, reg, reg_read(encoder, reg) & ~val);
+}
+
+static void
+tda998x_reset(struct drm_encoder *encoder)
+{
+	/* reset audio and i2c master: */
+	reg_set(encoder, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
+	msleep(50);
+	reg_clear(encoder, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
+	msleep(50);
+
+	/* reset transmitter: */
+	reg_set(encoder, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
+	reg_clear(encoder, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
+
+	/* PLL registers common configuration */
+	reg_write(encoder, REG_PLL_SERIAL_1, 0x00);
+	reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1));
+	reg_write(encoder, REG_PLL_SERIAL_3, 0x00);
+	reg_write(encoder, REG_SERIALIZER,   0x00);
+	reg_write(encoder, REG_BUFFER_OUT,   0x00);
+	reg_write(encoder, REG_PLL_SCG1,     0x00);
+	reg_write(encoder, REG_AUDIO_DIV,    0x03);
+	reg_write(encoder, REG_SEL_CLK,      SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
+	reg_write(encoder, REG_PLL_SCGN1,    0xfa);
+	reg_write(encoder, REG_PLL_SCGN2,    0x00);
+	reg_write(encoder, REG_PLL_SCGR1,    0x5b);
+	reg_write(encoder, REG_PLL_SCGR2,    0x00);
+	reg_write(encoder, REG_PLL_SCG2,     0x10);
+}
+
+/* DRM encoder functions */
+
+static void
+tda998x_encoder_set_config(struct drm_encoder *encoder, void *params)
+{
+}
+
+static void
+tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct tda998x_priv *priv = to_tda998x_priv(encoder);
+
+	/* we only care about on or off: */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
+	if (mode == priv->dpms)
+		return;
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		/* enable audio and video ports */
+		reg_write(encoder, REG_ENA_AP, 0x03);
+		reg_write(encoder, REG_ENA_VP_0, 0xff);
+		reg_write(encoder, REG_ENA_VP_1, 0xff);
+		reg_write(encoder, REG_ENA_VP_2, 0xff);
+		/* set muxing after enabling ports: */
+		reg_write(encoder, REG_VIP_CNTRL_0,
+				VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3));
+		reg_write(encoder, REG_VIP_CNTRL_1,
+				VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1));
+		reg_write(encoder, REG_VIP_CNTRL_2,
+				VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5));
+		break;
+	case DRM_MODE_DPMS_OFF:
+		/* disable audio and video ports */
+		reg_write(encoder, REG_ENA_AP, 0x00);
+		reg_write(encoder, REG_ENA_VP_0, 0x00);
+		reg_write(encoder, REG_ENA_VP_1, 0x00);
+		reg_write(encoder, REG_ENA_VP_2, 0x00);
+		break;
+	}
+
+	priv->dpms = mode;
+}
+
+static void
+tda998x_encoder_save(struct drm_encoder *encoder)
+{
+	DBG("");
+}
+
+static void
+tda998x_encoder_restore(struct drm_encoder *encoder)
+{
+	DBG("");
+}
+
+static bool
+tda998x_encoder_mode_fixup(struct drm_encoder *encoder,
+			  const struct drm_display_mode *mode,
+			  struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static int
+tda998x_encoder_mode_valid(struct drm_encoder *encoder,
+			  struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+
+static void
+tda998x_audio_infoframe_enable(struct drm_encoder *encoder)
+{
+	uint8_t buffer[20];
+	struct hdmi_audio_infoframe audio_frame;
+	size_t len;
+
+	hdmi_audio_infoframe_init(&audio_frame);
+
+	/* NXP audio is fixed at these values for the time being */
+	audio_frame.channels = 2;
+	audio_frame.coding_type = HDMI_AUDIO_CODING_TYPE_PCM;
+	audio_frame.sample_size = HDMI_AUDIO_SAMPLE_SIZE_24;
+	audio_frame.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_48000;
+
+	len = hdmi_audio_infoframe_pack(&audio_frame, buffer, sizeof(buffer));
+	WARN(len < 0, "hdmi_avi_infoframe_pack failed\n");
+
+	reg_write_range(encoder, REG_AUDIO_IF, buffer, len);
+
+	/* enable Audio Infoframe output in DIP_IF Register */
+	reg_clear(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF4);
+	udelay(5);
+	reg_set(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF4);
+}
+
+static void
+tda998x_avi_infoframe_enable(struct drm_encoder *encoder,
+			struct drm_display_mode *mode)
+{
+	uint8_t buffer[20];
+	struct hdmi_avi_infoframe avi_frame;
+	size_t len;
+
+	hdmi_avi_infoframe_init(&avi_frame);
+	avi_frame.video_code = drm_match_cea_mode(mode);
+	avi_frame.picture_aspect = HDMI_PICTURE_ASPECT_NONE;
+	avi_frame.active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
+	len = hdmi_avi_infoframe_pack(&avi_frame, buffer, sizeof(buffer));
+	WARN(len < 0, "hdmi_avi_infoframe_pack failed\n");
+
+	reg_write_range(encoder, REG_AVI_IF, buffer, len);
+
+	/* 
+	 * enable AVI Infoframe output in DIP_IF Register, but toggle it 
+	 * so that the hardware acknowledges that the packet data might have
+	 * changed
+	 */
+	reg_clear(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF2);
+	udelay(5);
+	reg_set(encoder, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF2);
+}
+
+/* lookup table for CEA values to VIDFORMAT values taken from NXP datasheet */
+static char cea_to_nxp_mode[34] = {-1, 0, 1, 1, 2, 3, 4, 4, 5, 5, -1, -1, 
+		-1, -1, -1, -1, 6, 7, 7, 8, 9, 10, 10,
+		11, 11, -1, -1, -1, -1, -1, -1, 12, 13};
+
+static char tda998x_cea_to_vidformat(unsigned char cea_mode)
+{
+	if(cea_mode > (sizeof(cea_to_nxp_mode) -1) ) {
+		return -1;
+	}
+	return cea_to_nxp_mode[cea_mode];
+}
+
+static char tda998x_is_monitor_hdmi(struct drm_encoder *encoder)
+{
+	struct edid *edid = (struct edid *)do_get_edid(encoder);
+	char hdmi = 0;
+	if(edid) {
+		hdmi = drm_detect_hdmi_monitor(edid);
+		kfree(edid);
+	} else {
+		return -1;
+	}
+	return hdmi;
+}
+
+
+static void
+tda998x_encoder_mode_set(struct drm_encoder *encoder,
+			struct drm_display_mode *mode,
+			struct drm_display_mode *adjusted_mode)
+{
+	struct tda998x_priv *priv = to_tda998x_priv(encoder);
+	uint16_t hs_start, hs_end, line_start, line_end;
+	uint16_t vwin_start, vwin_end, de_start, de_end;
+	uint16_t ref_pix, ref_line, pix_start2;
+	uint8_t reg, div, rep;
+
+	hs_start   = mode->hsync_start - mode->hdisplay;
+	hs_end     = mode->hsync_end - mode->hdisplay;
+	line_start = 1;
+	line_end   = 1 + mode->vsync_end - mode->vsync_start;
+	vwin_start = mode->vtotal - mode->vsync_start;
+	vwin_end   = vwin_start + mode->vdisplay;
+	de_start   = mode->htotal - mode->hdisplay;
+	de_end     = mode->htotal;
+
+	pix_start2 = 0;
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		pix_start2 = (mode->htotal / 2) + hs_start;
+
+	/* TODO how is this value calculated?  It is 2 for all common
+	 * formats in the tables in out of tree nxp driver (assuming
+	 * I've properly deciphered their byzantine table system)
+	 */
+	ref_line = 2;
+
+	/* this might changes for other color formats from the CRTC: */
+	ref_pix = 3 + hs_start;
+
+	div = 148500 / mode->clock;
+
+	DBG("clock=%d, div=%u", mode->clock, div);
+	DBG("hs_start=%u, hs_end=%u, line_start=%u, line_end=%u",
+			hs_start, hs_end, line_start, line_end);
+	DBG("vwin_start=%u, vwin_end=%u, de_start=%u, de_end=%u",
+			vwin_start, vwin_end, de_start, de_end);
+	DBG("ref_line=%u, ref_pix=%u, pix_start2=%u",
+			ref_line, ref_pix, pix_start2);
+
+	/* mute the audio FIFO: */
+	reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
+
+	/*  HDMI/HDCP mode off... for now...: */
+	reg_set(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
+	reg_clear(encoder, REG_TX33, TX33_HDMI);
+
+	reg_write(encoder, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(0));
+	/* no pre-filter or interpolator: */
+	reg_write(encoder, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) |
+			HVF_CNTRL_0_INTPOL(0));
+	reg_write(encoder, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
+	reg_write(encoder, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) |
+			VIP_CNTRL_4_BLC(0));
+	reg_clear(encoder, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR);
+
+	reg_clear(encoder, REG_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IZ);
+	reg_clear(encoder, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE);
+	reg_write(encoder, REG_SERIALIZER, 0);
+	reg_write(encoder, REG_HVF_CNTRL_1, HVF_CNTRL_1_VQR(0));
+
+	/* TODO enable pixel repeat for pixel rates less than 25Msamp/s */
+	rep = 0;
+	reg_write(encoder, REG_RPT_CNTRL, 0);
+	reg_write(encoder, REG_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) |
+			SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
+
+	reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
+			PLL_SERIAL_2_SRL_PR(rep));
+
+	reg_write16(encoder, REG_VS_PIX_STRT_2_MSB, pix_start2);
+	reg_write16(encoder, REG_VS_PIX_END_2_MSB, pix_start2);
+
+	/* set color matrix bypass flag: */
+	reg_set(encoder, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP);
+
+	/* set BIAS tmds value: */
+	reg_write(encoder, REG_ANA_GENERAL, 0x09);
+
+	reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD);
+
+	reg_write(encoder, REG_VIP_CNTRL_3, 0);
+	reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_SYNC_HS);
+	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+		reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_V_TGL);
+
+	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+		reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL);
+
+	reg_write(encoder, REG_VIDFORMAT, 0x00);
+	reg_write16(encoder, REG_NPIX_MSB, mode->hdisplay - 1);
+	reg_write16(encoder, REG_NLINE_MSB, mode->vdisplay - 1);
+	reg_write16(encoder, REG_VS_LINE_STRT_1_MSB, line_start);
+	reg_write16(encoder, REG_VS_LINE_END_1_MSB, line_end);
+	reg_write16(encoder, REG_VS_PIX_STRT_1_MSB, hs_start);
+	reg_write16(encoder, REG_VS_PIX_END_1_MSB, hs_start);
+	reg_write16(encoder, REG_HS_PIX_START_MSB, hs_start);
+	reg_write16(encoder, REG_HS_PIX_STOP_MSB, hs_end);
+	reg_write16(encoder, REG_VWIN_START_1_MSB, vwin_start);
+	reg_write16(encoder, REG_VWIN_END_1_MSB, vwin_end);
+	reg_write16(encoder, REG_DE_START_MSB, de_start);
+	reg_write16(encoder, REG_DE_STOP_MSB, de_end);
+
+	if (priv->rev == TDA19988) {
+		/* let incoming pixels fill the active space (if any) */
+		reg_write(encoder, REG_ENABLE_SPACE, 0x01);
+	}
+
+	reg_write16(encoder, REG_REFPIX_MSB, ref_pix);
+	reg_write16(encoder, REG_REFLINE_MSB, ref_line);
+
+	reg = TBG_CNTRL_1_VHX_EXT_DE |
+			TBG_CNTRL_1_VHX_EXT_HS |
+			TBG_CNTRL_1_VHX_EXT_VS |
+	  		TBG_CNTRL_1_DWIN_DIS | /* HDCP off */
+			TBG_CNTRL_1_VH_TGL_2;
+	if (mode->flags & (DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC))
+		reg |= TBG_CNTRL_1_VH_TGL_0;
+	reg_set(encoder, REG_TBG_CNTRL_1, reg);
+
+
+
+
+	if(tda998x_is_monitor_hdmi(encoder) == 1) {
+		char vidformat;
+		vidformat = tda998x_cea_to_vidformat(drm_match_cea_mode(mode));
+		if(vidformat == (char)-1) {
+			dev_err(encoder->dev->dev, "Not sure which CEA mode to set, leaving as DVI");
+			goto out;
+		}
+		dev_info(encoder->dev->dev, "Connected to an HDMI monitor with cea mode %d", vidformat);
+			
+		/* this is an HDMI monitor, so set things up a bit differently */
+		reg_write(encoder, REG_TBG_CNTRL_1, 0);
+		reg_write(encoder, REG_VIDFORMAT, vidformat);
+		/* get the infoframes pumping */
+		tda998x_avi_infoframe_enable(encoder, mode);
+		tda998x_audio_infoframe_enable(encoder);
+		reg_set(encoder, REG_TX33, TX33_HDMI);
+
+		/* set up audio registers */
+		reg_write(encoder, REG_ACR_CTS_0, 0x0);
+		reg_write(encoder, REG_ACR_CTS_1, 0x0);
+		reg_write(encoder, REG_ACR_CTS_2, 0x0);
+
+		reg_write(encoder, REG_ACR_N_0, 0x0);
+		reg_write(encoder, REG_ACR_N_1, 0x18);
+		reg_write(encoder, REG_ACR_N_2, 0x0);
+
+		reg_set(encoder, REG_DIP_FLAGS, DIP_FLAGS_ACR);
+
+		reg_write(encoder, REG_ENC_CNTRL, 0x04);
+		reg_write(encoder, REG_CTS_N, 0x33);
+		/* Set 2 channel I2S mode */
+		reg_write(encoder, REG_ENA_AP, 0x3);
+
+		/* set audio divider in pll settings */
+		reg_write(encoder, REG_AUDIO_DIV, 0x2);
+
+		/* select the audio input port clock */
+		reg_write(encoder, REG_AIP_CLKSEL, SEL_AIP_I2S);
+		reg_write(encoder, REG_MUX_AP, MUX_AP_SELECT_I2S);
+
+		/* select I2S format, and datasize */
+		reg_write(encoder, REG_I2S_FORMAT, 0x0a);
+
+		/* enable the audio FIFO: */
+		reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
+
+		/* mute and then unmute, to get audio going */
+		reg_write(encoder, REG_GC_AVMUTE, GC_AVMUTE_SETMUTE);
+		reg_write(encoder, REG_GC_AVMUTE, GC_AVMUTE_CLRMUTE);
+	}
+out:
+	/* must be last register set: */
+	reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
+
+}
+
+static enum drm_connector_status
+tda998x_encoder_detect(struct drm_encoder *encoder,
+		      struct drm_connector *connector)
+{
+	uint8_t val = cec_read(encoder, REG_CEC_RXSHPDLEV);
+	return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected :
+			connector_status_disconnected;
+}
+
+static int
+read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
+{
+	uint8_t offset, segptr;
+	int ret, i;
+
+	/* enable EDID read irq: */
+	reg_set(encoder, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
+
+	offset = (blk & 1) ? 128 : 0;
+	segptr = blk / 2;
+
+	reg_write(encoder, REG_DDC_ADDR, 0xa0);
+	reg_write(encoder, REG_DDC_OFFS, offset);
+	reg_write(encoder, REG_DDC_SEGM_ADDR, 0x60);
+	reg_write(encoder, REG_DDC_SEGM, segptr);
+
+	/* enable reading EDID: */
+	reg_write(encoder, REG_EDID_CTRL, 0x1);
+
+	/* flag must be cleared by sw: */
+	reg_write(encoder, REG_EDID_CTRL, 0x0);
+
+	/* wait for block read to complete: */
+	for (i = 100; i > 0; i--) {
+		uint8_t val = reg_read(encoder, REG_INT_FLAGS_2);
+		if (val & INT_FLAGS_2_EDID_BLK_RD)
+			break;
+		msleep(1);
+	}
+
+	if (i == 0)
+		return -ETIMEDOUT;
+
+	ret = reg_read_range(encoder, REG_EDID_DATA_0, buf, EDID_LENGTH);
+	if (ret != EDID_LENGTH) {
+		dev_err(encoder->dev->dev, "failed to read edid block %d: %d",
+				blk, ret);
+		return ret;
+	}
+
+	reg_clear(encoder, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
+
+	return 0;
+}
+
+static uint8_t *
+do_get_edid(struct drm_encoder *encoder)
+{
+	int j = 0, valid_extensions = 0;
+	uint8_t *block, *new;
+	bool print_bad_edid = drm_debug & DRM_UT_KMS;
+
+	if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
+		return NULL;
+
+	/* base block fetch */
+	if (read_edid_block(encoder, block, 0))
+		goto fail;
+
+	if (!drm_edid_block_valid(block, 0, print_bad_edid))
+		goto fail;
+
+	/* if there's no extensions, we're done */
+	if (block[0x7e] == 0)
+		return block;
+
+	new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
+	if (!new)
+		goto fail;
+	block = new;
+
+	for (j = 1; j <= block[0x7e]; j++) {
+		uint8_t *ext_block = block + (valid_extensions + 1) * EDID_LENGTH;
+		if (read_edid_block(encoder, ext_block, j))
+			goto fail;
+
+		if (!drm_edid_block_valid(ext_block, j, print_bad_edid))
+			goto fail;
+
+		valid_extensions++;
+	}
+
+	if (valid_extensions != block[0x7e]) {
+		block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
+		block[0x7e] = valid_extensions;
+		new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
+		if (!new)
+			goto fail;
+		block = new;
+	}
+
+	return block;
+
+fail:
+	dev_warn(encoder->dev->dev, "failed to read EDID\n");
+	kfree(block);
+	return NULL;
+}
+
+static int
+tda998x_encoder_get_modes(struct drm_encoder *encoder,
+			 struct drm_connector *connector)
+{
+	struct edid *edid = (struct edid *)do_get_edid(encoder);
+	int n = 0;
+
+	if (edid) {
+		drm_mode_connector_update_edid_property(connector, edid);
+		n = drm_add_edid_modes(connector, edid);
+		kfree(edid);
+	}
+
+	return n;
+}
+
+static int
+tda998x_encoder_create_resources(struct drm_encoder *encoder,
+				struct drm_connector *connector)
+{
+	DBG("");
+	return 0;
+}
+
+static int
+tda998x_encoder_set_property(struct drm_encoder *encoder,
+			    struct drm_connector *connector,
+			    struct drm_property *property,
+			    uint64_t val)
+{
+	DBG("");
+	return 0;
+}
+
+static void
+tda998x_encoder_destroy(struct drm_encoder *encoder)
+{
+	struct tda998x_priv *priv = to_tda998x_priv(encoder);
+	drm_i2c_encoder_destroy(encoder);
+	kfree(priv);
+}
+
+static struct drm_encoder_slave_funcs tda998x_encoder_funcs = {
+	.set_config = tda998x_encoder_set_config,
+	.destroy = tda998x_encoder_destroy,
+	.dpms = tda998x_encoder_dpms,
+	.save = tda998x_encoder_save,
+	.restore = tda998x_encoder_restore,
+	.mode_fixup = tda998x_encoder_mode_fixup,
+	.mode_valid = tda998x_encoder_mode_valid,
+	.mode_set = tda998x_encoder_mode_set,
+	.detect = tda998x_encoder_detect,
+	.get_modes = tda998x_encoder_get_modes,
+	.create_resources = tda998x_encoder_create_resources,
+	.set_property = tda998x_encoder_set_property,
+};
+
+/* I2C driver functions */
+
+static int
+tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	return 0;
+}
+
+static int
+tda998x_remove(struct i2c_client *client)
+{
+	return 0;
+}
+
+static int
+tda998x_encoder_init(struct i2c_client *client,
+		    struct drm_device *dev,
+		    struct drm_encoder_slave *encoder_slave)
+{
+	struct drm_encoder *encoder = &encoder_slave->base;
+	struct tda998x_priv *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->current_page = 0;
+	priv->cec = i2c_new_dummy(client->adapter, 0x34);
+	priv->dpms = DRM_MODE_DPMS_OFF;
+
+	encoder_slave->slave_priv = priv;
+	encoder_slave->slave_funcs = &tda998x_encoder_funcs;
+
+	/* wake up the device: */
+	cec_write(encoder, REG_CEC_ENAMODS,
+			CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI);
+
+	tda998x_reset(encoder);
+
+	/* read version: */
+	priv->rev = reg_read(encoder, REG_VERSION_LSB) |
+			reg_read(encoder, REG_VERSION_MSB) << 8;
+
+	/* mask off feature bits: */
+	priv->rev &= ~0x30; /* not-hdcp and not-scalar bit */
+
+	switch (priv->rev) {
+	case TDA9989N2:  dev_info(dev->dev, "found TDA9989 n2");  break;
+	case TDA19989:   dev_info(dev->dev, "found TDA19989");    break;
+	case TDA19989N2: dev_info(dev->dev, "found TDA19989 n2"); break;
+	case TDA19988:   dev_info(dev->dev, "found TDA19988");    break;
+	default:
+		DBG("found unsupported device: %04x", priv->rev);
+		goto fail;
+	}
+
+	/* after reset, enable DDC: */
+	reg_write(encoder, REG_DDC_DISABLE, 0x00);
+
+	/* set clock on DDC channel: */
+	reg_write(encoder, REG_TX3, 39);
+
+	/* if necessary, disable multi-master: */
+	if (priv->rev == TDA19989)
+		reg_set(encoder, REG_I2C_MASTER, I2C_MASTER_DIS_MM);
+
+	cec_write(encoder, REG_CEC_FRO_IM_CLK_CTRL,
+			CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL);
+
+	return 0;
+
+fail:
+	/* if encoder_init fails, the encoder slave is never registered,
+	 * so cleanup here:
+	 */
+	if (priv->cec)
+		i2c_unregister_device(priv->cec);
+	kfree(priv);
+	encoder_slave->slave_priv = NULL;
+	encoder_slave->slave_funcs = NULL;
+	return -ENXIO;
+}
+
+static struct i2c_device_id tda998x_ids[] = {
+	{ "tda998x", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tda998x_ids);
+
+static struct drm_i2c_encoder_driver tda998x_driver = {
+	.i2c_driver = {
+		.probe = tda998x_probe,
+		.remove = tda998x_remove,
+		.driver = {
+			.name = "tda998x",
+		},
+		.id_table = tda998x_ids,
+	},
+	.encoder_init = tda998x_encoder_init,
+};
+
+/* Module initialization */
+
+static int __init
+tda998x_init(void)
+{
+	DBG("");
+	return drm_i2c_encoder_register(THIS_MODULE, &tda998x_driver);
+}
+
+static void __exit
+tda998x_exit(void)
+{
+	DBG("");
+	drm_i2c_encoder_unregister(&tda998x_driver);
+}
+
+MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
+MODULE_DESCRIPTION("NXP Semiconductors TDA998X HDMI Encoder");
+MODULE_LICENSE("GPL");
+
+module_init(tda998x_init);
+module_exit(tda998x_exit);
+
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig
index 8a55bee..47ccc1a 100644
--- a/drivers/gpu/drm/nouveau/Kconfig
+++ b/drivers/gpu/drm/nouveau/Kconfig
@@ -52,26 +52,3 @@ config DRM_NOUVEAU_BACKLIGHT
 	help
 	  Say Y here if you want to control the backlight of your display
 	  (e.g. a laptop panel).
-
-menu "I2C encoder or helper chips"
-     depends on DRM && DRM_KMS_HELPER && I2C
-
-config DRM_I2C_CH7006
-	tristate "Chrontel ch7006 TV encoder"
-	default m if DRM_NOUVEAU
-	help
-	  Support for Chrontel ch7006 and similar TV encoders, found
-	  on some nVidia video cards.
-
-	  This driver is currently only useful if you're also using
-	  the nouveau driver.
-
-config DRM_I2C_SIL164
-	tristate "Silicon Image sil164 TMDS transmitter"
-	default m if DRM_NOUVEAU
-	help
-	  Support for sil164 and similar single-link (or dual-link
-	  when used in pairs) TMDS transmitters, used in some nVidia
-	  video cards.
-
-endmenu
diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c
index 62e826a..4a69ccd 100644
--- a/drivers/gpu/drm/nouveau/nv04_tv.c
+++ b/drivers/gpu/drm/nouveau/nv04_tv.c
@@ -184,14 +184,23 @@ static const struct drm_encoder_funcs nv04_tv_funcs = {
 	.destroy = nv04_tv_destroy,
 };
 
+static const struct drm_encoder_helper_funcs nv04_tv_helper_funcs = {
+	.dpms = nv04_tv_dpms,
+	.save = drm_i2c_encoder_save,
+	.restore = drm_i2c_encoder_restore,
+	.mode_fixup = drm_i2c_encoder_mode_fixup,
+	.prepare = nv04_tv_prepare,
+	.commit = nv04_tv_commit,
+	.mode_set = nv04_tv_mode_set,
+	.detect = drm_i2c_encoder_detect,
+};
+
 int
 nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
 {
 	struct nouveau_encoder *nv_encoder;
 	struct drm_encoder *encoder;
 	struct drm_device *dev = connector->dev;
-	struct drm_encoder_helper_funcs *hfuncs;
-	struct drm_encoder_slave_funcs *sfuncs;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
 	struct nouveau_i2c_port *port = i2c->find(i2c, entry->i2c_index);
@@ -207,17 +216,11 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
 	if (!nv_encoder)
 		return -ENOMEM;
 
-	hfuncs = kzalloc(sizeof(*hfuncs), GFP_KERNEL);
-	if (!hfuncs) {
-		ret = -ENOMEM;
-		goto fail_free;
-	}
-
 	/* Initialize the common members */
 	encoder = to_drm_encoder(nv_encoder);
 
 	drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC);
-	drm_encoder_helper_add(encoder, hfuncs);
+	drm_encoder_helper_add(encoder, &nv04_tv_helper_funcs);
 
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_clones = 0;
@@ -230,30 +233,14 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
 	if (ret < 0)
 		goto fail_cleanup;
 
-	/* Fill the function pointers */
-	sfuncs = get_slave_funcs(encoder);
-
-	*hfuncs = (struct drm_encoder_helper_funcs) {
-		.dpms = nv04_tv_dpms,
-		.save = sfuncs->save,
-		.restore = sfuncs->restore,
-		.mode_fixup = sfuncs->mode_fixup,
-		.prepare = nv04_tv_prepare,
-		.commit = nv04_tv_commit,
-		.mode_set = nv04_tv_mode_set,
-		.detect = sfuncs->detect,
-	};
-
 	/* Attach it to the specified connector. */
-	sfuncs->create_resources(encoder, connector);
+	get_slave_funcs(encoder)->create_resources(encoder, connector);
 	drm_mode_connector_attach_encoder(connector, encoder);
 
 	return 0;
 
 fail_cleanup:
 	drm_encoder_cleanup(encoder);
-	kfree(hfuncs);
-fail_free:
 	kfree(nv_encoder);
 	return ret;
 }
diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig
new file mode 100644
index 0000000..d2928c7
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/Kconfig
@@ -0,0 +1,13 @@
+config DRM_TILCDC
+	tristate "DRM Support for TI LCDC Display Controller"
+	depends on DRM && OF && BACKLIGHT_LCD_SUPPORT
+	select DRM_KMS_HELPER
+	select DRM_KMS_CMA_HELPER
+	select DRM_GEM_CMA_HELPER
+	select OF_VIDEOMODE
+	select OF_DISPLAY_TIMING
+	select BACKLIGHT_CLASS_DEVICE
+	help
+	  Choose this option if you have an TI SoC with LCDC display
+	  controller, for example AM33xx in beagle-bone, DA8xx, or
+	  OMAP-L1xx.  This driver replaces the FB_DA8XX fbdev driver.
diff --git a/drivers/gpu/drm/tilcdc/Makefile b/drivers/gpu/drm/tilcdc/Makefile
new file mode 100644
index 0000000..deda656
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/Makefile
@@ -0,0 +1,10 @@
+ccflags-y := -Iinclude/drm -Werror
+
+tilcdc-y := \
+	tilcdc_crtc.o \
+	tilcdc_tfp410.o \
+	tilcdc_slave.o \
+	tilcdc_panel.o \
+	tilcdc_drv.o
+
+obj-$(CONFIG_DRM_TILCDC)	+= tilcdc.o
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
new file mode 100644
index 0000000..375986e
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -0,0 +1,801 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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/kfifo.h>
+
+#include "tilcdc_drv.h"
+#include "tilcdc_regs.h"
+
+struct tilcdc_crtc {
+	struct drm_crtc base;
+
+	const struct tilcdc_panel_info *info;
+	uint32_t dirty;
+	dma_addr_t start, end;
+	struct drm_pending_vblank_event *event;
+	int dpms;
+	wait_queue_head_t frame_done_wq;
+	bool frame_done;
+
+	/* fb currently set to scanout 0/1: */
+	struct drm_framebuffer *scanout[2];
+
+	/* for deferred fb unref's: */
+	DECLARE_KFIFO_PTR(unref_fifo, struct drm_framebuffer *);
+	struct work_struct work;
+};
+#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)
+
+static void unref_worker(struct work_struct *work)
+{
+	struct tilcdc_crtc *tilcdc_crtc = container_of(work, struct tilcdc_crtc, work);
+	struct drm_device *dev = tilcdc_crtc->base.dev;
+	struct drm_framebuffer *fb;
+
+	mutex_lock(&dev->mode_config.mutex);
+	while (kfifo_get(&tilcdc_crtc->unref_fifo, &fb))
+		drm_framebuffer_unreference(fb);
+	mutex_unlock(&dev->mode_config.mutex);
+}
+
+static void set_scanout(struct drm_crtc *crtc, int n)
+{
+	static const uint32_t base_reg[] = {
+			LCDC_DMA_FB_BASE_ADDR_0_REG, LCDC_DMA_FB_BASE_ADDR_1_REG,
+	};
+	static const uint32_t ceil_reg[] = {
+			LCDC_DMA_FB_CEILING_ADDR_0_REG, LCDC_DMA_FB_CEILING_ADDR_1_REG,
+	};
+	static const uint32_t stat[] = {
+			LCDC_END_OF_FRAME0, LCDC_END_OF_FRAME1,
+	};
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+
+	tilcdc_write(dev, base_reg[n], tilcdc_crtc->start);
+	tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end);
+	if (tilcdc_crtc->scanout[n]) {
+		if (kfifo_put(&tilcdc_crtc->unref_fifo,
+				(const struct drm_framebuffer **)&tilcdc_crtc->scanout[n])) {
+			struct tilcdc_drm_private *priv = dev->dev_private;
+			queue_work(priv->wq, &tilcdc_crtc->work);
+		} else {
+			dev_err(dev->dev, "unref fifo full!\n");
+			drm_framebuffer_unreference(tilcdc_crtc->scanout[n]);
+		}
+	}
+	tilcdc_crtc->scanout[n] = crtc->fb;
+	drm_framebuffer_reference(tilcdc_crtc->scanout[n]);
+	tilcdc_crtc->dirty &= ~stat[n];
+}
+
+static void update_scanout(struct drm_crtc *crtc)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct drm_framebuffer *fb = crtc->fb;
+	struct drm_gem_cma_object *gem;
+	unsigned int depth, bpp;
+
+	drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	tilcdc_crtc->start = gem->paddr + fb->offsets[0] +
+			(crtc->y * fb->pitches[0]) + (crtc->x * bpp/8);
+
+	tilcdc_crtc->end = tilcdc_crtc->start +
+			(crtc->mode.vdisplay * fb->pitches[0]);
+
+	if (tilcdc_crtc->dpms == DRM_MODE_DPMS_ON) {
+		/* already enabled, so just mark the frames that need
+		 * updating and they will be updated on vblank:
+		 */
+		tilcdc_crtc->dirty |= LCDC_END_OF_FRAME0 | LCDC_END_OF_FRAME1;
+		drm_vblank_get(dev, 0);
+	} else {
+		/* not enabled yet, so update registers immediately: */
+		set_scanout(crtc, 0);
+		set_scanout(crtc, 1);
+	}
+}
+
+static void start(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
+
+	if (priv->rev == 2) {
+		tilcdc_set(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET);
+		msleep(1);
+		tilcdc_clear(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET);
+		msleep(1);
+	}
+
+	tilcdc_set(dev, LCDC_DMA_CTRL_REG, LCDC_DUAL_FRAME_BUFFER_ENABLE);
+	tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_PALETTE_LOAD_MODE(DATA_ONLY));
+	tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
+}
+
+static void stop(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+
+	tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
+}
+
+static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+
+	WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON);
+
+	drm_crtc_cleanup(crtc);
+	WARN_ON(!kfifo_is_empty(&tilcdc_crtc->unref_fifo));
+	kfifo_free(&tilcdc_crtc->unref_fifo);
+	kfree(tilcdc_crtc);
+}
+
+static int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
+		struct drm_framebuffer *fb,
+		struct drm_pending_vblank_event *event)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+
+	if (tilcdc_crtc->event) {
+		dev_err(dev->dev, "already pending page flip!\n");
+		return -EBUSY;
+	}
+
+	crtc->fb = fb;
+	tilcdc_crtc->event = event;
+	pm_runtime_get_sync(dev->dev);
+	update_scanout(crtc);
+	pm_runtime_put_sync(dev->dev);
+
+	return 0;
+}
+
+static void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
+
+	/* we really only care about on or off: */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
+	if (tilcdc_crtc->dpms == mode)
+		return;
+
+	tilcdc_crtc->dpms = mode;
+
+	pm_runtime_get_sync(dev->dev);
+
+	if (mode == DRM_MODE_DPMS_ON) {
+		pm_runtime_forbid(dev->dev);
+		start(crtc);
+	} else {
+		tilcdc_crtc->frame_done = false;
+		stop(crtc);
+
+		/* if necessary wait for framedone irq which will still come
+		 * before putting things to sleep..
+		 */
+		if (priv->rev == 2) {
+			int ret = wait_event_timeout(
+					tilcdc_crtc->frame_done_wq,
+					tilcdc_crtc->frame_done,
+					msecs_to_jiffies(50));
+			if (ret == 0)
+				dev_err(dev->dev, "timeout waiting for framedone\n");
+		}
+		pm_runtime_allow(dev->dev);
+	}
+
+	pm_runtime_put_sync(dev->dev);
+}
+
+static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
+		const struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void tilcdc_crtc_prepare(struct drm_crtc *crtc)
+{
+	tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void tilcdc_crtc_commit(struct drm_crtc *crtc)
+{
+	tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+static int tilcdc_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 *old_fb)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	const struct tilcdc_panel_info *info = tilcdc_crtc->info;
+	uint32_t reg, hbp, hfp, hsw, vbp, vfp, vsw;
+	int ret;
+
+	ret = tilcdc_crtc_mode_valid(crtc, mode, 0, 0, NULL);
+	if (WARN_ON(ret))
+		return ret;
+
+	if (WARN_ON(!info))
+		return -EINVAL;
+
+	pm_runtime_get_sync(dev->dev);
+
+	/* Configure the Burst Size and fifo threshold of DMA: */
+	reg = tilcdc_read(dev, LCDC_DMA_CTRL_REG) & ~0x00000770;
+	switch (info->dma_burst_sz) {
+	case 1:
+		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_1);
+		break;
+	case 2:
+		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_2);
+		break;
+	case 4:
+		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_4);
+		break;
+	case 8:
+		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_8);
+		break;
+	case 16:
+		reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_16);
+		break;
+	default:
+		return -EINVAL;
+	}
+	reg |= (info->fifo_th << 8);
+	tilcdc_write(dev, LCDC_DMA_CTRL_REG, reg);
+
+	/* Configure timings: */
+	hbp = mode->htotal - mode->hsync_end;
+	hfp = mode->hsync_start - mode->hdisplay;
+	hsw = mode->hsync_end - mode->hsync_start;
+	vbp = mode->vtotal - mode->vsync_end;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vsw = mode->vsync_end - mode->vsync_start;
+
+	DBG("%dx%d, hbp=%u, hfp=%u, hsw=%u, vbp=%u, vfp=%u, vsw=%u",
+			mode->hdisplay, mode->vdisplay, hbp, hfp, hsw, vbp, vfp, vsw);
+
+	/* Configure the AC Bias Period and Number of Transitions per Interrupt: */
+	reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG);
+	reg &= ~0x000fff00;
+	reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) |
+		LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt);
+
+	/* subtract one from hfp, hbp, hsw because the hardware uses a value of 0 as 1 */
+	if (priv->rev == 2) {
+		/* clear bits we're going to set */
+		reg &= ~0x78000033;
+		reg |= ((hfp-1) & 0x300) >> 8;
+		reg |= ((hbp-1) & 0x300) >> 4;
+		reg |= ((hsw-1) & 0x3c0) << 21;
+	}
+	tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg);
+
+	/* subtract one from hfp, hbp, hsw because the hardware uses a value of 0 as 1 */
+	/* weirdly on BeagleBone Black) the hbp is still wrong when analyzed on hdmi timing tool */
+	/* all other values come out correct - need to look into why this is happening */
+	/* might be something that is happening after the LCD output in the hdmi encoder */
+	reg = (((mode->hdisplay >> 4) - 1) << 4) |
+	    (((hbp-1) & 0xff) << 24) |
+	    (((hfp-1) & 0xff) << 16) |
+	    (((hsw-1) & 0x3f) << 10);
+	if (priv->rev == 2)
+		reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
+
+	tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg);
+
+	/* only the vertical sync width maps 0 as 1 so only subtract 1 from vsw */
+	reg = ((mode->vdisplay - 1) & 0x3ff) |
+	    ((vbp & 0xff) << 24) |
+	    ((vfp & 0xff) << 16) |
+	    (((vsw-1) & 0x3f) << 10);
+	tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg);
+
+        if (priv->rev == 2) {
+		if ((mode->vdisplay - 1) & 0x400)
+			tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_LPP_B10);
+		else
+			tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_LPP_B10);
+        }
+
+	/* Configure display type: */
+	reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) &
+	    ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE |
+	      LCDC_V2_TFT_24BPP_MODE | LCDC_V2_TFT_24BPP_UNPACK | 0x000ff000);
+	reg |= LCDC_TFT_MODE; /* no monochrome/passive support */
+	if (info->tft_alt_mode)
+		reg |= LCDC_TFT_ALT_ENABLE;
+	if (priv->rev == 2) {
+		unsigned int depth, bpp;
+
+		drm_fb_get_bpp_depth(crtc->fb->pixel_format, &depth, &bpp);
+		switch (bpp) {
+		case 16:
+			break;
+		case 32:
+		        reg |= LCDC_V2_TFT_24BPP_UNPACK;
+			/* fallthrough */
+		case 24:
+			reg |= LCDC_V2_TFT_24BPP_MODE;
+			break;
+		default:
+			dev_err(dev->dev, "invalid pixel format\n");
+			return -EINVAL;
+		}
+	}
+	reg |= info->fdd < 12;
+	tilcdc_write(dev, LCDC_RASTER_CTRL_REG, reg);
+
+	if (info->invert_pxl_clk)
+		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
+	else
+		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
+
+	if (info->sync_ctrl)
+		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
+	else
+		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
+
+	if (info->sync_edge)
+		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
+	else
+		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
+
+	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
+	else
+		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
+
+	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+		tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
+	else
+		tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
+
+	if (info->raster_order)
+		tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
+	else
+		tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
+
+
+	update_scanout(crtc);
+	tilcdc_crtc_update_clk(crtc);
+
+	pm_runtime_put_sync(dev->dev);
+
+	return 0;
+}
+
+static int tilcdc_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+		struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+
+	pm_runtime_get_sync(dev->dev);
+	update_scanout(crtc);
+	pm_runtime_put_sync(dev->dev);
+	return 0;
+}
+
+static void tilcdc_crtc_load_lut(struct drm_crtc *crtc)
+{
+}
+
+static const struct drm_crtc_funcs tilcdc_crtc_funcs = {
+		.destroy        = tilcdc_crtc_destroy,
+		.set_config     = drm_crtc_helper_set_config,
+		.page_flip      = tilcdc_crtc_page_flip,
+};
+
+static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
+		.dpms           = tilcdc_crtc_dpms,
+		.mode_fixup     = tilcdc_crtc_mode_fixup,
+		.prepare        = tilcdc_crtc_prepare,
+		.commit         = tilcdc_crtc_commit,
+		.mode_set       = tilcdc_crtc_mode_set,
+		.mode_set_base  = tilcdc_crtc_mode_set_base,
+		.load_lut       = tilcdc_crtc_load_lut,
+};
+
+int tilcdc_crtc_max_width(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	int max_width = 0;
+
+	if (priv->rev == 1)
+		max_width = 1024;
+	else if (priv->rev == 2)
+		max_width = 2048;
+
+	return max_width;
+}
+
+/* this should find it's way to DT */
+static int audio_mode_check(int hdisplay, int vdisplay, int refresh,
+		int cea_mode)
+{
+	/* only cea modes can handle audio */
+	if (cea_mode <= 0)
+		return 0;
+
+	/* hardcoded mode that supports audio (at 24Hz) */
+	if (hdisplay == 1920 && vdisplay == 1080 && refresh == 24)
+		return 1;
+
+	/* from the rest, only those modes that refresh at 50/60 */
+	if (refresh != 50 && refresh != 60)
+		return 0;
+
+	return 1;
+}
+
+int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+		int rb_check, int audio, struct edid *edid)
+{
+  	struct tilcdc_drm_private *priv = crtc->dev->dev_private;
+	unsigned int bandwidth;
+	uint32_t hbp, hfp, hsw, vbp, vfp, vsw;
+	int has_audio, is_cea_mode, can_output_audio, refresh;
+	uint8_t cea_mode;
+
+	int rb;
+
+	/* check to see if the width is within the range that the LCD Controller physically supports */
+	if (mode->hdisplay > tilcdc_crtc_max_width(crtc)) {
+		return MODE_VIRTUAL_X;
+	}
+
+	/* width must be multiple of 16 */
+	if (mode->hdisplay & 0xf)
+		return MODE_VIRTUAL_X;
+
+	if (mode->vdisplay > 2048)
+		return MODE_VIRTUAL_Y;
+
+	/* set if there's audio capability */
+	has_audio = edid && drm_detect_monitor_audio(edid);
+
+	/* only 50 & 60Hz modes reliably support audio */
+	refresh = drm_mode_vrefresh(mode);
+
+	/* set if it's a cea mode */
+	cea_mode = drm_match_cea_mode(mode);
+	is_cea_mode = cea_mode > 0;
+
+	/* set if we can output audio */
+	can_output_audio = edid && has_audio &&
+			audio_mode_check(mode->hdisplay, mode->vdisplay,
+					refresh, cea_mode);
+
+	DBG("mode %dx%d@%d pixel-clock %d audio %s cea %s can_output %s",
+		mode->hdisplay, mode->vdisplay, refresh,
+		mode->clock,
+		has_audio ? "true" : "false",
+		is_cea_mode ? "true" : "false",
+		can_output_audio ? "true" : "false" );
+
+	/* we only prune the mode if we ask for it */
+	if (audio && edid && has_audio && !can_output_audio) {
+		DBG("Pruning mode : Does not support audio");
+		return MODE_BAD;
+	}
+
+	hbp = mode->htotal - mode->hsync_end;
+	hfp = mode->hsync_start - mode->hdisplay;
+	hsw = mode->hsync_end - mode->hsync_start;
+	vbp = mode->vtotal - mode->vsync_end;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vsw = mode->vsync_end - mode->vsync_start;
+
+	if (hbp & ~0x3ff) {
+		DBG("Pruning mode : Horizontal Back Porch out of range");
+		return MODE_BAD;
+	}
+
+	if (hfp & ~0x3ff) {
+		DBG("Pruning mode : Horizontal Front Porch out of range");
+		return MODE_BAD;
+	}
+
+	if (hsw & ~0x3ff) {
+		DBG("Pruning mode : Horizontal Sync Width out of range");
+		return MODE_BAD;
+	}
+
+	if (vbp & ~0xff) {
+		DBG("Pruning mode : Vertical Back Porch out of range");
+		return MODE_BAD;
+	}
+
+	if (vfp & ~0xff) {
+		DBG("Pruning mode : Vertical Front Porch out of range");
+		return MODE_BAD;
+	}
+
+	if (vsw & ~0x3f) {
+		DBG("Pruning mode : Vertical Sync Width out of range");
+		return MODE_BAD;
+	}
+
+	/* some devices have a maximum allowed pixel clock */
+	/* configured from the DT */
+	if (mode->clock > priv->max_pixelclock) {
+		DBG("Pruning mode, pixel clock too high");
+		return MODE_BAD;
+	}
+
+	/* some devices further limit the max horizontal resolution */
+	/* configured from the DT */
+	if (mode->hdisplay > priv->max_width) {
+		DBG("Pruning mode, above max width of %d supported by device", priv->max_width);
+		return MODE_BAD;
+	}
+
+	/* filter out modes that would require too much memory bandwidth: */
+	/* configured from the DT */
+	bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode);
+	if (bandwidth > priv->max_bandwidth) {
+		DBG("Pruning mode, exceeds defined bandwidth limit");
+		return MODE_BAD;
+	}
+
+	if (rb_check) {
+		/* we only support reduced blanking modes */
+		rb = (mode->htotal - mode->hdisplay == 160) &&
+			(mode->hsync_end - mode->hdisplay == 80) &&
+			(mode->hsync_end - mode->hsync_start == 32) &&
+			(mode->vsync_start - mode->vdisplay == 3);
+		if (!rb) {
+			DBG("Pruning mode, only support reduced blanking modes");
+			return MODE_BAD;
+		}
+	}
+
+	return MODE_OK;
+}
+
+void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
+		const struct tilcdc_panel_info *info)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	tilcdc_crtc->info = info;
+}
+
+void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	int dpms = tilcdc_crtc->dpms;
+	unsigned int lcd_clk, div;
+	int ret;
+
+	pm_runtime_get_sync(dev->dev);
+
+	if (dpms == DRM_MODE_DPMS_ON)
+		tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+
+	/* in raster mode, minimum divisor is 2: */
+	ret = clk_set_rate(priv->disp_clk, crtc->mode.clock * 1000 * 2);
+	if (ret) {
+		dev_err(dev->dev, "failed to set display clock rate to: %d\n",
+				crtc->mode.clock);
+		goto out;
+	}
+
+	lcd_clk = clk_get_rate(priv->clk);
+	div = lcd_clk / (crtc->mode.clock * 1000);
+
+	DBG("lcd_clk=%u, mode clock=%d, div=%u", lcd_clk, crtc->mode.clock, div);
+	DBG("fck=%lu, dpll_disp_ck=%lu", clk_get_rate(priv->clk), clk_get_rate(priv->disp_clk));
+
+	/* Configure the LCD clock divisor. */
+	tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(div) |
+			LCDC_RASTER_MODE);
+
+	if (priv->rev == 2)
+		tilcdc_set(dev, LCDC_CLK_ENABLE_REG,
+				LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN |
+				LCDC_V2_CORE_CLK_EN);
+
+	if (dpms == DRM_MODE_DPMS_ON)
+		tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+
+out:
+	pm_runtime_put_sync(dev->dev);
+}
+
+irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	uint32_t stat = tilcdc_read_irqstatus(dev);
+
+	if ((stat & LCDC_SYNC_LOST) && (stat & LCDC_FIFO_UNDERFLOW)) {
+		stop(crtc);
+		dev_err(dev->dev, "error: %08x\n", stat);
+		tilcdc_clear_irqstatus(dev, stat);
+		start(crtc);
+	} else if (stat & LCDC_PL_LOAD_DONE) {
+		tilcdc_clear_irqstatus(dev, stat);
+	} else {
+		struct drm_pending_vblank_event *event;
+		unsigned long flags;
+		uint32_t dirty = tilcdc_crtc->dirty & stat;
+
+		tilcdc_clear_irqstatus(dev, stat);
+
+		if (dirty & LCDC_END_OF_FRAME0)
+			set_scanout(crtc, 0);
+
+		if (dirty & LCDC_END_OF_FRAME1)
+			set_scanout(crtc, 1);
+
+		drm_handle_vblank(dev, 0);
+
+		spin_lock_irqsave(&dev->event_lock, flags);
+		event = tilcdc_crtc->event;
+		tilcdc_crtc->event = NULL;
+		if (event)
+			drm_send_vblank_event(dev, 0, event);
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+
+		if (dirty && !tilcdc_crtc->dirty)
+			drm_vblank_put(dev, 0);
+	}
+
+	if (priv->rev == 2) {
+		if (stat & LCDC_FRAME_DONE) {
+			tilcdc_crtc->frame_done = true;
+			wake_up(&tilcdc_crtc->frame_done_wq);
+		}
+		tilcdc_write(dev, LCDC_END_OF_INT_IND_REG, 0);
+	}
+
+	return IRQ_HANDLED;
+}
+
+void tilcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct drm_pending_vblank_event *event;
+	struct drm_device *dev = crtc->dev;
+	unsigned long flags;
+
+	/* Destroy the pending vertical blanking event associated with the
+	 * pending page flip, if any, and disable vertical blanking interrupts.
+	 */
+	spin_lock_irqsave(&dev->event_lock, flags);
+	event = tilcdc_crtc->event;
+	if (event && event->base.file_priv == file) {
+		tilcdc_crtc->event = NULL;
+		event->base.destroy(&event->base);
+		drm_vblank_put(dev, 0);
+	}
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
+{
+	struct tilcdc_crtc *tilcdc_crtc;
+	struct drm_crtc *crtc;
+	int ret;
+
+	tilcdc_crtc = kzalloc(sizeof(*tilcdc_crtc), GFP_KERNEL);
+	if (!tilcdc_crtc) {
+		dev_err(dev->dev, "allocation failed\n");
+		return NULL;
+	}
+
+	crtc = &tilcdc_crtc->base;
+
+	tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF;
+	init_waitqueue_head(&tilcdc_crtc->frame_done_wq);
+
+	ret = kfifo_alloc(&tilcdc_crtc->unref_fifo, 16, GFP_KERNEL);
+	if (ret) {
+		dev_err(dev->dev, "could not allocate unref FIFO\n");
+		goto fail;
+	}
+
+	INIT_WORK(&tilcdc_crtc->work, unref_worker);
+
+	ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs);
+	if (ret < 0)
+		goto fail;
+
+	drm_crtc_helper_add(crtc, &tilcdc_crtc_helper_funcs);
+
+	return crtc;
+
+fail:
+	tilcdc_crtc_destroy(crtc);
+	return NULL;
+}
+
+struct tilcdc_panel_info *tilcdc_of_get_panel_info(struct device_node *np)
+{
+	struct device_node *info_np;
+	struct tilcdc_panel_info *info;
+	int ret = 0;
+
+	if (!np)
+		return NULL;
+
+	info_np = of_get_child_by_name(np, "panel-info");
+	if (!info_np) {
+		pr_err("%s: could not find panel-info node\n",
+				of_node_full_name(np));
+		return NULL;
+	}
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		pr_err("%s: allocation failed\n",
+				of_node_full_name(np));
+		goto err_no_mem;
+	}
+
+	ret |= of_property_read_u32(info_np, "ac-bias", &info->ac_bias);
+	ret |= of_property_read_u32(info_np, "ac-bias-intrpt", &info->ac_bias_intrpt);
+	ret |= of_property_read_u32(info_np, "dma-burst-sz", &info->dma_burst_sz);
+	ret |= of_property_read_u32(info_np, "bpp", &info->bpp);
+	ret |= of_property_read_u32(info_np, "fdd", &info->fdd);
+	ret |= of_property_read_u32(info_np, "sync-edge", &info->sync_edge);
+	ret |= of_property_read_u32(info_np, "sync-ctrl", &info->sync_ctrl);
+	ret |= of_property_read_u32(info_np, "raster-order", &info->raster_order);
+	ret |= of_property_read_u32(info_np, "fifo-th", &info->fifo_th);
+
+	/* optional: */
+	info->tft_alt_mode      = of_property_read_bool(info_np, "tft-alt-mode");
+	info->invert_pxl_clk    = of_property_read_bool(info_np, "invert-pxl-clk");
+
+	if (ret) {
+		pr_err("%s: error reading panel-info properties\n",
+				of_node_full_name(info_np));
+		goto err_bad_prop;
+	}
+
+	/* release ref */
+	of_node_put(info_np);
+
+	return info;
+
+err_bad_prop:
+	kfree(info);
+err_no_mem:
+	of_node_put(info_np);
+	return NULL;
+}
+
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
new file mode 100644
index 0000000..85f972f
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -0,0 +1,661 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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/>.
+ */
+
+/* LCDC DRM driver, based on da8xx-fb */
+
+#include "tilcdc_drv.h"
+#include "tilcdc_regs.h"
+#include "tilcdc_tfp410.h"
+#include "tilcdc_slave.h"
+#include "tilcdc_panel.h"
+
+#include "drm_fb_helper.h"
+
+#include <linux/of_gpio.h>
+
+static LIST_HEAD(module_list);
+
+void tilcdc_module_init(struct tilcdc_module *mod, const char *name,
+		const struct tilcdc_module_ops *funcs)
+{
+	mod->name = name;
+	mod->funcs = funcs;
+	INIT_LIST_HEAD(&mod->list);
+	list_add(&mod->list, &module_list);
+}
+
+void tilcdc_module_cleanup(struct tilcdc_module *mod)
+{
+	list_del(&mod->list);
+}
+
+static struct of_device_id tilcdc_of_match[];
+
+static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev,
+		struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	return drm_fb_cma_create(dev, file_priv, mode_cmd);
+}
+
+static void tilcdc_fb_output_poll_changed(struct drm_device *dev)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	if (priv->fbdev)
+		drm_fbdev_cma_hotplug_event(priv->fbdev);
+}
+
+static const struct drm_mode_config_funcs mode_config_funcs = {
+	.fb_create = tilcdc_fb_create,
+	.output_poll_changed = tilcdc_fb_output_poll_changed,
+};
+
+static int modeset_init(struct drm_device *dev)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	struct tilcdc_module *mod;
+
+	drm_mode_config_init(dev);
+
+	priv->crtc = tilcdc_crtc_create(dev);
+
+	list_for_each_entry(mod, &module_list, list) {
+		DBG("loading module: %s", mod->name);
+		mod->funcs->modeset_init(mod, dev);
+	}
+
+	if ((priv->num_encoders = 0) || (priv->num_connectors == 0)) {
+		/* oh nos! */
+		dev_err(dev->dev, "no encoders/connectors found\n");
+		return -ENXIO;
+	}
+
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+	dev->mode_config.max_width = tilcdc_crtc_max_width(priv->crtc);
+	dev->mode_config.max_height = 2048;
+	dev->mode_config.funcs = &mode_config_funcs;
+
+	return 0;
+}
+
+#ifdef CONFIG_CPU_FREQ
+static int cpufreq_transition(struct notifier_block *nb,
+				     unsigned long val, void *data)
+{
+	struct tilcdc_drm_private *priv = container_of(nb,
+			struct tilcdc_drm_private, freq_transition);
+	if (val == CPUFREQ_POSTCHANGE) {
+		if (priv->lcd_fck_rate != clk_get_rate(priv->clk)) {
+			priv->lcd_fck_rate = clk_get_rate(priv->clk);
+			tilcdc_crtc_update_clk(priv->crtc);
+		}
+	}
+
+	return 0;
+}
+#endif
+
+/*
+ * DRM operations:
+ */
+
+static int tilcdc_unload(struct drm_device *dev)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	struct tilcdc_module *mod, *cur;
+
+	drm_kms_helper_poll_fini(dev);
+	drm_mode_config_cleanup(dev);
+	drm_vblank_cleanup(dev);
+
+	pm_runtime_get_sync(dev->dev);
+	drm_irq_uninstall(dev);
+	pm_runtime_put_sync(dev->dev);
+
+#ifdef CONFIG_CPU_FREQ
+	cpufreq_unregister_notifier(&priv->freq_transition,
+			CPUFREQ_TRANSITION_NOTIFIER);
+#endif
+
+	if (priv->clk)
+		clk_put(priv->clk);
+
+	if (priv->mmio)
+		iounmap(priv->mmio);
+
+	flush_workqueue(priv->wq);
+	destroy_workqueue(priv->wq);
+
+	pm_runtime_disable(dev->dev);
+
+	list_for_each_entry_safe(mod, cur, &module_list, list) {
+		DBG("destroying module: %s", mod->name);
+		mod->funcs->destroy(mod, dev);
+	}
+
+	dev->dev_private = NULL;
+
+	kfree(priv);
+
+	return 0;
+}
+
+static int tilcdc_load(struct drm_device *dev, unsigned long flags)
+{
+	struct platform_device *pdev = dev->platformdev;
+	struct device_node *node = pdev->dev.of_node;
+	struct tilcdc_drm_private *priv;
+	struct resource *res;
+	enum of_gpio_flags ofgpioflags;
+	unsigned long gpioflags;
+	int gpio, ret;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(dev->dev, "failed to allocate private data\n");
+		return -ENOMEM;
+	}
+
+	dev->dev_private = priv;
+
+	priv->wq = alloc_ordered_workqueue("tilcdc", 0);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev->dev, "failed to get memory resource\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	priv->mmio = ioremap_nocache(res->start, resource_size(res));
+	if (!priv->mmio) {
+		dev_err(dev->dev, "failed to ioremap\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	priv->clk = clk_get(dev->dev, "fck");
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev->dev, "failed to get functional clock\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	priv->disp_clk = clk_get(dev->dev, "dpll_disp_ck");
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev->dev, "failed to get display clock\n");
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	/* some devices have a power gpio control */
+	gpio = of_get_named_gpio_flags(pdev->dev.of_node, "ti,power-gpio",
+                       0, &ofgpioflags);
+	if (IS_ERR_VALUE(gpio)) {
+		dev_info(&pdev->dev, "No power control GPIO\n");
+	} else {
+		gpioflags = GPIOF_DIR_OUT;
+		if (ofgpioflags & OF_GPIO_ACTIVE_LOW) {
+			gpioflags |= GPIOF_INIT_LOW;
+			dev_info(&pdev->dev, "Power GPIO active low, initial state set to low\n");
+		} else {
+			gpioflags |= GPIOF_INIT_HIGH;
+			dev_info(&pdev->dev, "Power GPIO active high, initial state set to high\n");
+		}
+		ret = devm_gpio_request_one(&pdev->dev, gpio,
+		gpioflags, "lcdc_drv:PDN");
+		if (ret != 0) {
+			dev_err(&pdev->dev, "Failed to request power gpio\n");
+			goto fail;
+		}
+	}
+
+#ifdef CONFIG_CPU_FREQ
+	priv->lcd_fck_rate = clk_get_rate(priv->clk);
+	priv->freq_transition.notifier_call = cpufreq_transition;
+	ret = cpufreq_register_notifier(&priv->freq_transition,
+			CPUFREQ_TRANSITION_NOTIFIER);
+	if (ret) {
+		dev_err(dev->dev, "failed to register cpufreq notifier\n");
+		goto fail;
+	}
+#endif
+
+	if (of_property_read_u32(node, "ti,max-bandwidth", &priv->max_bandwidth))
+		priv->max_bandwidth = TILCDC_DEFAULT_MAX_BANDWIDTH;
+
+	DBG("Maximum Bandwidth Value %d", priv->max_bandwidth);
+
+	if (of_property_read_u32(node, "ti,max-width", &priv->max_width))
+		priv->max_width = TILCDC_DEFAULT_MAX_WIDTH;
+
+	DBG("Maximum Horizontal Pixel Width Value %dpixels", priv->max_width);
+
+	if (of_property_read_u32(node, "ti,max-pixelclock", &priv->max_pixelclock))
+		priv->max_pixelclock = TILCDC_DEFAULT_MAX_PIXELCLOCK;
+
+	DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock);
+
+	priv->allow_non_rblank = of_property_read_bool(node,
+			"ti,allow-non-reduced-blanking-modes");
+
+	DBG("Allowing Standard Monitor Modes: %s",
+			priv->allow_non_rblank ? "true" : "false");
+
+	priv->allow_non_audio = of_property_read_bool(node,
+			"ti,allow-non-audio-modes");
+
+	DBG("Allowing Non Audio Monitor Modes: %s",
+			priv->allow_non_audio ? "true" : "false");
+
+	pm_runtime_enable(dev->dev);
+
+	/* Determine LCD IP Version */
+	pm_runtime_get_sync(dev->dev);
+	switch (tilcdc_read(dev, LCDC_PID_REG)) {
+	case 0x4c100102:
+		priv->rev = 1;
+		break;
+	case 0x4f200800:
+	case 0x4f201000:
+		priv->rev = 2;
+		break;
+	default:
+		dev_warn(dev->dev, "Unknown PID Reg value 0x%08x, "
+				"defaulting to LCD revision 1\n",
+				tilcdc_read(dev, LCDC_PID_REG));
+		priv->rev = 1;
+		break;
+	}
+
+	pm_runtime_put_sync(dev->dev);
+
+	ret = modeset_init(dev);
+	if (ret < 0) {
+		dev_err(dev->dev, "failed to initialize mode setting\n");
+		goto fail;
+	}
+
+	ret = drm_vblank_init(dev, 1);
+	if (ret < 0) {
+		dev_err(dev->dev, "failed to initialize vblank\n");
+		goto fail;
+	}
+
+	pm_runtime_get_sync(dev->dev);
+	ret = drm_irq_install(dev);
+	pm_runtime_put_sync(dev->dev);
+	if (ret < 0) {
+		dev_err(dev->dev, "failed to install IRQ handler\n");
+		goto fail;
+	}
+
+	platform_set_drvdata(pdev, dev);
+
+	priv->fbdev = drm_fbdev_cma_init(dev, 16,
+			dev->mode_config.num_crtc,
+			dev->mode_config.num_connector);
+
+	drm_kms_helper_poll_init(dev);
+
+	return 0;
+
+fail:
+	tilcdc_unload(dev);
+	return ret;
+}
+
+static void tilcdc_preclose(struct drm_device *dev, struct drm_file *file)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+
+	tilcdc_crtc_cancel_page_flip(priv->crtc, file);
+}
+
+static void tilcdc_lastclose(struct drm_device *dev)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	drm_fbdev_cma_restore_mode(priv->fbdev);
+}
+
+static irqreturn_t tilcdc_irq(DRM_IRQ_ARGS)
+{
+	struct drm_device *dev = arg;
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	return tilcdc_crtc_irq(priv->crtc);
+}
+
+static void tilcdc_irq_preinstall(struct drm_device *dev)
+{
+	tilcdc_clear_irqstatus(dev, 0xffffffff);
+}
+
+static int tilcdc_irq_postinstall(struct drm_device *dev)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+
+	/* enable FIFO underflow irq: */
+	if (priv->rev == 1) {
+		tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_UNDERFLOW_INT_ENA);
+	} else {
+		tilcdc_set(dev, LCDC_INT_ENABLE_SET_REG, LCDC_V2_UNDERFLOW_INT_ENA);
+	}
+
+	return 0;
+}
+
+static void tilcdc_irq_uninstall(struct drm_device *dev)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+
+	/* disable irqs that we might have enabled: */
+	if (priv->rev == 1) {
+		tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
+				LCDC_V1_UNDERFLOW_INT_ENA | LCDC_V1_PL_INT_ENA);
+		tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_V1_END_OF_FRAME_INT_ENA);
+	} else {
+		tilcdc_clear(dev, LCDC_INT_ENABLE_SET_REG,
+			LCDC_V2_UNDERFLOW_INT_ENA | LCDC_V2_PL_INT_ENA |
+			LCDC_V2_END_OF_FRAME0_INT_ENA | LCDC_V2_END_OF_FRAME1_INT_ENA |
+			LCDC_FRAME_DONE);
+	}
+
+}
+
+static void enable_vblank(struct drm_device *dev, bool enable)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	u32 reg, mask;
+
+	if (priv->rev == 1) {
+		reg = LCDC_DMA_CTRL_REG;
+		mask = LCDC_V1_END_OF_FRAME_INT_ENA;
+	} else {
+		reg = LCDC_INT_ENABLE_SET_REG;
+		mask = LCDC_V2_END_OF_FRAME0_INT_ENA |
+			LCDC_V2_END_OF_FRAME1_INT_ENA | LCDC_FRAME_DONE;
+	}
+
+	if (enable)
+		tilcdc_set(dev, reg, mask);
+	else
+		tilcdc_clear(dev, reg, mask);
+}
+
+static int tilcdc_enable_vblank(struct drm_device *dev, int crtc)
+{
+	enable_vblank(dev, true);
+	return 0;
+}
+
+static void tilcdc_disable_vblank(struct drm_device *dev, int crtc)
+{
+	enable_vblank(dev, false);
+}
+
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_PM_SLEEP)
+static const struct {
+	const char *name;
+	uint8_t  rev;
+	uint8_t  save;
+	uint32_t reg;
+} registers[] = 	{
+#define REG(rev, save, reg) { #reg, rev, save, reg }
+		/* exists in revision 1: */
+		REG(1, false, LCDC_PID_REG),
+		REG(1, true,  LCDC_CTRL_REG),
+		REG(1, false, LCDC_STAT_REG),
+		REG(1, true,  LCDC_RASTER_CTRL_REG),
+		REG(1, true,  LCDC_RASTER_TIMING_0_REG),
+		REG(1, true,  LCDC_RASTER_TIMING_1_REG),
+		REG(1, true,  LCDC_RASTER_TIMING_2_REG),
+		REG(1, true,  LCDC_DMA_CTRL_REG),
+		REG(1, true,  LCDC_DMA_FB_BASE_ADDR_0_REG),
+		REG(1, true,  LCDC_DMA_FB_CEILING_ADDR_0_REG),
+		REG(1, true,  LCDC_DMA_FB_BASE_ADDR_1_REG),
+		REG(1, true,  LCDC_DMA_FB_CEILING_ADDR_1_REG),
+		/* new in revision 2: */
+		REG(2, false, LCDC_RAW_STAT_REG),
+		REG(2, false, LCDC_MASKED_STAT_REG),
+		REG(2, false, LCDC_INT_ENABLE_SET_REG),
+		REG(2, false, LCDC_INT_ENABLE_CLR_REG),
+		REG(2, false, LCDC_END_OF_INT_IND_REG),
+		REG(2, true,  LCDC_CLK_ENABLE_REG),
+		REG(2, true,  LCDC_INT_ENABLE_SET_REG),
+#undef REG
+};
+#endif
+
+#ifdef CONFIG_DEBUG_FS
+static int tilcdc_regs_show(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	unsigned i;
+
+	pm_runtime_get_sync(dev->dev);
+
+	seq_printf(m, "revision: %d\n", priv->rev);
+
+	for (i = 0; i < ARRAY_SIZE(registers); i++)
+		if (priv->rev >= registers[i].rev)
+			seq_printf(m, "%s:\t %08x\n", registers[i].name,
+					tilcdc_read(dev, registers[i].reg));
+
+	pm_runtime_put_sync(dev->dev);
+
+	return 0;
+}
+
+static int tilcdc_mm_show(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	return drm_mm_dump_table(m, dev->mm_private);
+}
+
+static struct drm_info_list tilcdc_debugfs_list[] = {
+		{ "regs", tilcdc_regs_show, 0 },
+		{ "mm",   tilcdc_mm_show,   0 },
+		{ "fb",   drm_fb_cma_debugfs_show, 0 },
+};
+
+static int tilcdc_debugfs_init(struct drm_minor *minor)
+{
+	struct drm_device *dev = minor->dev;
+	struct tilcdc_module *mod;
+	int ret;
+
+	ret = drm_debugfs_create_files(tilcdc_debugfs_list,
+			ARRAY_SIZE(tilcdc_debugfs_list),
+			minor->debugfs_root, minor);
+
+	list_for_each_entry(mod, &module_list, list)
+		if (mod->funcs->debugfs_init)
+			mod->funcs->debugfs_init(mod, minor);
+
+	if (ret) {
+		dev_err(dev->dev, "could not install tilcdc_debugfs_list\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static void tilcdc_debugfs_cleanup(struct drm_minor *minor)
+{
+	struct tilcdc_module *mod;
+	drm_debugfs_remove_files(tilcdc_debugfs_list,
+			ARRAY_SIZE(tilcdc_debugfs_list), minor);
+
+	list_for_each_entry(mod, &module_list, list)
+		if (mod->funcs->debugfs_cleanup)
+			mod->funcs->debugfs_cleanup(mod, minor);
+}
+#endif
+
+static const struct file_operations fops = {
+	.owner              = THIS_MODULE,
+	.open               = drm_open,
+	.release            = drm_release,
+	.unlocked_ioctl     = drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl       = drm_compat_ioctl,
+#endif
+	.poll               = drm_poll,
+	.read               = drm_read,
+	.fasync             = drm_fasync,
+	.llseek             = no_llseek,
+	.mmap               = drm_gem_cma_mmap,
+};
+
+static struct drm_driver tilcdc_driver = {
+	.driver_features    = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET,
+	.load               = tilcdc_load,
+	.unload             = tilcdc_unload,
+	.preclose           = tilcdc_preclose,
+	.lastclose          = tilcdc_lastclose,
+	.irq_handler        = tilcdc_irq,
+	.irq_preinstall     = tilcdc_irq_preinstall,
+	.irq_postinstall    = tilcdc_irq_postinstall,
+	.irq_uninstall      = tilcdc_irq_uninstall,
+	.get_vblank_counter = drm_vblank_count,
+	.enable_vblank      = tilcdc_enable_vblank,
+	.disable_vblank     = tilcdc_disable_vblank,
+	.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,
+#ifdef CONFIG_DEBUG_FS
+	.debugfs_init       = tilcdc_debugfs_init,
+	.debugfs_cleanup    = tilcdc_debugfs_cleanup,
+#endif
+	.fops               = &fops,
+	.name               = "tilcdc",
+	.desc               = "TI LCD Controller DRM",
+	.date               = "20121205",
+	.major              = 1,
+	.minor              = 0,
+};
+
+/*
+ * Power management:
+ */
+
+#ifdef CONFIG_PM_SLEEP
+static int tilcdc_pm_suspend(struct device *dev)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+	struct tilcdc_drm_private *priv = ddev->dev_private;
+	unsigned i, n = 0;
+
+	drm_kms_helper_poll_disable(ddev);
+
+	/* Save register state: */
+	for (i = 0; i < ARRAY_SIZE(registers); i++)
+		if (registers[i].save && (priv->rev >= registers[i].rev))
+			priv->saved_register[n++] = tilcdc_read(ddev, registers[i].reg);
+
+	return 0;
+}
+
+static int tilcdc_pm_resume(struct device *dev)
+{
+	struct drm_device *ddev = dev_get_drvdata(dev);
+	struct tilcdc_drm_private *priv = ddev->dev_private;
+	unsigned i, n = 0;
+
+	/* Restore register state: */
+	for (i = 0; i < ARRAY_SIZE(registers); i++)
+		if (registers[i].save && (priv->rev >= registers[i].rev))
+			tilcdc_write(ddev, registers[i].reg, priv->saved_register[n++]);
+
+	drm_kms_helper_poll_enable(ddev);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops tilcdc_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(tilcdc_pm_suspend, tilcdc_pm_resume)
+};
+
+/*
+ * Platform driver:
+ */
+
+static int tilcdc_pdev_probe(struct platform_device *pdev)
+{
+	/* bail out early if no DT data: */
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev, "device-tree data is missing\n");
+		return -ENXIO;
+	}
+
+	return drm_platform_init(&tilcdc_driver, pdev);
+}
+
+static int tilcdc_pdev_remove(struct platform_device *pdev)
+{
+	drm_platform_exit(&tilcdc_driver, pdev);
+
+	return 0;
+}
+
+static struct of_device_id tilcdc_of_match[] = {
+		{ .compatible = "ti,am33xx-tilcdc", },
+		{ },
+};
+MODULE_DEVICE_TABLE(of, tilcdc_of_match);
+
+static struct platform_driver tilcdc_platform_driver = {
+	.probe      = tilcdc_pdev_probe,
+	.remove     = tilcdc_pdev_remove,
+	.driver     = {
+		.owner  = THIS_MODULE,
+		.name   = "tilcdc",
+		.pm     = &tilcdc_pm_ops,
+		.of_match_table = tilcdc_of_match,
+	},
+};
+
+static int __init tilcdc_drm_init(void)
+{
+	DBG("init");
+	tilcdc_tfp410_init();
+	tilcdc_slave_init();
+	tilcdc_panel_init();
+	return platform_driver_register(&tilcdc_platform_driver);
+}
+
+static void __exit tilcdc_drm_fini(void)
+{
+	DBG("fini");
+	tilcdc_tfp410_fini();
+	tilcdc_slave_fini();
+	tilcdc_panel_fini();
+	platform_driver_unregister(&tilcdc_platform_driver);
+}
+
+late_initcall(tilcdc_drm_init);
+module_exit(tilcdc_drm_fini);
+
+MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
+MODULE_DESCRIPTION("TI LCD Controller DRM Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
new file mode 100644
index 0000000..d869519
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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 __TILCDC_DRV_H__
+#define __TILCDC_DRV_H__
+
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/list.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+
+/* Defaulting to pixel clock defined on AM335x */
+#define TILCDC_DEFAULT_MAX_PIXELCLOCK  126000
+/* Defaulting to max width as defined on AM335x */
+#define TILCDC_DEFAULT_MAX_WIDTH  2048
+/* 
+ * This may need some tweaking, but want to allow at least 1280x1024@60 
+ * with optimized DDR & EMIF settings tweaked 1920x1080@25 appears to 
+ * be supportable 
+ * Note: 1920x1080x25=49766400 < 1280x1024x60=78643200
+ */
+#define TILCDC_DEFAULT_MAX_BANDWIDTH  (1280*1024*60)
+
+struct tilcdc_drm_private {
+	void __iomem *mmio;
+
+	struct clk *disp_clk;    /* display dpll */
+	struct clk *clk;         /* functional clock */
+	int rev;                 /* IP revision */
+
+	/* don't attempt resolutions w/ higher W * H * Hz: */
+	uint32_t max_bandwidth;
+	/* Pixel Clock will be restricted to some value as defined in the device datasheet */
+	/* measured in KHz */
+	uint32_t max_pixelclock;
+	/* Max allowable width is limited on a per device basis */
+	/* measured in pixels */
+	uint32_t max_width;
+
+	int allow_non_rblank;	/* ATM we don't support non reduced blank modes */
+	int allow_non_audio;	/* allow modes that don't have working audio */
+
+	/* register contents saved across suspend/resume: */
+	u32 saved_register[12];
+
+#ifdef CONFIG_CPU_FREQ
+	struct notifier_block freq_transition;
+	unsigned int lcd_fck_rate;
+#endif
+
+	struct workqueue_struct *wq;
+
+	struct drm_fbdev_cma *fbdev;
+
+	struct drm_crtc *crtc;
+
+	unsigned int num_encoders;
+	struct drm_encoder *encoders[8];
+
+	unsigned int num_connectors;
+	struct drm_connector *connectors[8];
+};
+
+/* Sub-module for display.  Since we don't know at compile time what panels
+ * or display adapter(s) might be present (for ex, off chip dvi/tfp410,
+ * hdmi encoder, various lcd panels), the connector/encoder(s) are split into
+ * separate drivers.  If they are probed and found to be present, they
+ * register themselves with tilcdc_register_module().
+ */
+struct tilcdc_module;
+
+struct tilcdc_module_ops {
+	/* create appropriate encoders/connectors: */
+	int (*modeset_init)(struct tilcdc_module *mod, struct drm_device *dev);
+	void (*destroy)(struct tilcdc_module *mod, struct drm_device *dev);
+#ifdef CONFIG_DEBUG_FS
+	/* create debugfs nodes (can be NULL): */
+	int (*debugfs_init)(struct tilcdc_module *mod, struct drm_minor *minor);
+	/* cleanup debugfs nodes (can be NULL): */
+	void (*debugfs_cleanup)(struct tilcdc_module *mod, struct drm_minor *minor);
+#endif
+};
+
+struct tilcdc_module {
+	const char *name;
+	struct list_head list;
+	const struct tilcdc_module_ops *funcs;
+};
+
+void tilcdc_module_init(struct tilcdc_module *mod, const char *name,
+		const struct tilcdc_module_ops *funcs);
+void tilcdc_module_cleanup(struct tilcdc_module *mod);
+
+
+/* Panel config that needs to be set in the crtc, but is not coming from
+ * the mode timings.  The display module is expected to call
+ * tilcdc_crtc_set_panel_info() to set this during modeset.
+ */
+struct tilcdc_panel_info {
+
+	/* AC Bias Pin Frequency */
+	uint32_t ac_bias;
+
+	/* AC Bias Pin Transitions per Interrupt */
+	uint32_t ac_bias_intrpt;
+
+	/* DMA burst size */
+	uint32_t dma_burst_sz;
+
+	/* Bits per pixel */
+	uint32_t bpp;
+
+	/* FIFO DMA Request Delay */
+	uint32_t fdd;
+
+	/* TFT Alternative Signal Mapping (Only for active) */
+	bool tft_alt_mode;
+
+	/* Invert pixel clock */
+	bool invert_pxl_clk;
+
+	/* Horizontal and Vertical Sync Edge: 0=rising 1=falling */
+	uint32_t sync_edge;
+
+	/* Horizontal and Vertical Sync: Control: 0=ignore */
+	uint32_t sync_ctrl;
+
+	/* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */
+	uint32_t raster_order;
+
+	/* DMA FIFO threshold */
+	uint32_t fifo_th;
+};
+
+#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+
+struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev);
+void tilcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
+irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc);
+void tilcdc_crtc_update_clk(struct drm_crtc *crtc);
+void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
+		const struct tilcdc_panel_info *info);
+int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode,
+		int rb_check, int audio, struct edid *edid);
+int tilcdc_crtc_max_width(struct drm_crtc *crtc);
+
+/* OF helper for reading panel info */
+struct tilcdc_panel_info *tilcdc_of_get_panel_info(struct device_node *np);
+
+#endif /* __TILCDC_DRV_H__ */
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
new file mode 100644
index 0000000..f690583
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/backlight.h>
+#include <video/display_timing.h>
+#include <video/of_display_timing.h>
+#include <video/videomode.h>
+#include <linux/of_gpio.h>
+
+#include "tilcdc_drv.h"
+
+struct panel_module {
+	struct tilcdc_module base;
+	struct tilcdc_panel_info *info;
+	struct display_timings *timings;
+	struct backlight_device *backlight;
+	int gpio;
+	struct pinctrl *pinctrl;
+	char *selected_state_name;
+};
+#define to_panel_module(x) container_of(x, struct panel_module, base)
+
+
+/*
+ * Encoder:
+ */
+
+struct panel_encoder {
+	struct drm_encoder base;
+	struct panel_module *mod;
+};
+#define to_panel_encoder(x) container_of(x, struct panel_encoder, base)
+
+
+static void panel_encoder_destroy(struct drm_encoder *encoder)
+{
+	struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
+	drm_encoder_cleanup(encoder);
+	kfree(panel_encoder);
+}
+
+static void panel_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
+	struct backlight_device *backlight = panel_encoder->mod->backlight;
+
+	if (!backlight)
+		return;
+
+	backlight->props.power = mode == DRM_MODE_DPMS_ON
+				     ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+	backlight_update_status(backlight);
+}
+
+static bool panel_encoder_mode_fixup(struct drm_encoder *encoder,
+		const struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	/* nothing needed */
+	return true;
+}
+
+static void panel_encoder_prepare(struct drm_encoder *encoder)
+{
+	struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
+	panel_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+	tilcdc_crtc_set_panel_info(encoder->crtc, panel_encoder->mod->info);
+}
+
+static void panel_encoder_commit(struct drm_encoder *encoder)
+{
+	panel_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static void panel_encoder_mode_set(struct drm_encoder *encoder,
+		struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	/* nothing needed */
+}
+
+static const struct drm_encoder_funcs panel_encoder_funcs = {
+		.destroy        = panel_encoder_destroy,
+};
+
+static const struct drm_encoder_helper_funcs panel_encoder_helper_funcs = {
+		.dpms           = panel_encoder_dpms,
+		.mode_fixup     = panel_encoder_mode_fixup,
+		.prepare        = panel_encoder_prepare,
+		.commit         = panel_encoder_commit,
+		.mode_set       = panel_encoder_mode_set,
+};
+
+static struct drm_encoder *panel_encoder_create(struct drm_device *dev,
+		struct panel_module *mod)
+{
+	struct panel_encoder *panel_encoder;
+	struct drm_encoder *encoder;
+	int ret;
+
+	panel_encoder = kzalloc(sizeof(*panel_encoder), GFP_KERNEL);
+	if (!panel_encoder) {
+		dev_err(dev->dev, "allocation failed\n");
+		return NULL;
+	}
+
+	panel_encoder->mod = mod;
+
+	encoder = &panel_encoder->base;
+	encoder->possible_crtcs = 1;
+
+	ret = drm_encoder_init(dev, encoder, &panel_encoder_funcs,
+			DRM_MODE_ENCODER_LVDS);
+	if (ret < 0)
+		goto fail;
+
+	drm_encoder_helper_add(encoder, &panel_encoder_helper_funcs);
+
+	return encoder;
+
+fail:
+	panel_encoder_destroy(encoder);
+	return NULL;
+}
+
+/*
+ * Connector:
+ */
+
+struct panel_connector {
+	struct drm_connector base;
+
+	struct drm_encoder *encoder;  /* our connected encoder */
+	struct panel_module *mod;
+};
+#define to_panel_connector(x) container_of(x, struct panel_connector, base)
+
+
+static void panel_connector_destroy(struct drm_connector *connector)
+{
+	struct panel_connector *panel_connector = to_panel_connector(connector);
+	drm_connector_cleanup(connector);
+	kfree(panel_connector);
+}
+
+static enum drm_connector_status panel_connector_detect(
+		struct drm_connector *connector,
+		bool force)
+{
+	return connector_status_connected;
+}
+
+static int panel_connector_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct panel_connector *panel_connector = to_panel_connector(connector);
+	struct display_timings *timings = panel_connector->mod->timings;
+	int i;
+
+	for (i = 0; i < timings->num_timings; i++) {
+		struct drm_display_mode *mode = drm_mode_create(dev);
+		struct videomode vm;
+
+		if (videomode_from_timing(timings, &vm, i))
+			break;
+
+		drm_display_mode_from_videomode(&vm, mode);
+
+		mode->type = DRM_MODE_TYPE_DRIVER;
+
+		if (timings->native_mode == i)
+			mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+		drm_mode_set_name(mode);
+		drm_mode_probed_add(connector, mode);
+	}
+
+	return i;
+}
+
+static int panel_connector_mode_valid(struct drm_connector *connector,
+		  struct drm_display_mode *mode)
+{
+	struct tilcdc_drm_private *priv = connector->dev->dev_private;
+	/* our only constraints are what the crtc can generate: */
+	return tilcdc_crtc_mode_valid(priv->crtc, mode, 0, 0, NULL);
+}
+
+static struct drm_encoder *panel_connector_best_encoder(
+		struct drm_connector *connector)
+{
+	struct panel_connector *panel_connector = to_panel_connector(connector);
+	return panel_connector->encoder;
+}
+
+static const struct drm_connector_funcs panel_connector_funcs = {
+	.destroy            = panel_connector_destroy,
+	.dpms               = drm_helper_connector_dpms,
+	.detect             = panel_connector_detect,
+	.fill_modes         = drm_helper_probe_single_connector_modes,
+};
+
+static const struct drm_connector_helper_funcs panel_connector_helper_funcs = {
+	.get_modes          = panel_connector_get_modes,
+	.mode_valid         = panel_connector_mode_valid,
+	.best_encoder       = panel_connector_best_encoder,
+};
+
+static struct drm_connector *panel_connector_create(struct drm_device *dev,
+		struct panel_module *mod, struct drm_encoder *encoder)
+{
+	struct panel_connector *panel_connector;
+	struct drm_connector *connector;
+	int ret;
+
+	panel_connector = kzalloc(sizeof(*panel_connector), GFP_KERNEL);
+	if (!panel_connector) {
+		dev_err(dev->dev, "allocation failed\n");
+		return NULL;
+	}
+
+	panel_connector->encoder = encoder;
+	panel_connector->mod = mod;
+
+	connector = &panel_connector->base;
+
+	drm_connector_init(dev, connector, &panel_connector_funcs,
+			DRM_MODE_CONNECTOR_LVDS);
+	drm_connector_helper_add(connector, &panel_connector_helper_funcs);
+
+	connector->interlace_allowed = 0;
+	connector->doublescan_allowed = 0;
+
+	ret = drm_mode_connector_attach_encoder(connector, encoder);
+	if (ret)
+		goto fail;
+
+	drm_sysfs_connector_add(connector);
+
+	return connector;
+
+fail:
+	panel_connector_destroy(connector);
+	return NULL;
+}
+
+/*
+ * Module:
+ */
+
+static int panel_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
+{
+	struct panel_module *panel_mod = to_panel_module(mod);
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+
+	encoder = panel_encoder_create(dev, panel_mod);
+	if (!encoder)
+		return -ENOMEM;
+
+	connector = panel_connector_create(dev, panel_mod, encoder);
+	if (!connector)
+		return -ENOMEM;
+
+	priv->encoders[priv->num_encoders++] = encoder;
+	priv->connectors[priv->num_connectors++] = connector;
+
+	return 0;
+}
+
+static void panel_destroy(struct tilcdc_module *mod, struct drm_device *dev)
+{
+	struct panel_module *panel_mod = to_panel_module(mod);
+
+	if (panel_mod->timings) {
+		display_timings_release(panel_mod->timings);
+		kfree(panel_mod->timings);
+	}
+
+	tilcdc_module_cleanup(mod);
+	kfree(panel_mod->info);
+	kfree(panel_mod);
+}
+
+static const struct tilcdc_module_ops panel_module_ops = {
+		.modeset_init = panel_modeset_init,
+		.destroy = panel_destroy,
+};
+
+/*
+ * Device:
+ */
+
+static struct of_device_id panel_of_match[];
+
+static ssize_t pinmux_show_state(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct panel_module *panel_mod = platform_get_drvdata(pdev);
+	const char *name;
+
+	name = panel_mod->selected_state_name;
+	if (name == NULL || strlen(name) == 0)
+		name = "none";
+	return sprintf(buf, "%s\n", name);
+}
+
+static ssize_t pinmux_store_state(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct panel_module *panel_mod = platform_get_drvdata(pdev);
+	struct pinctrl_state *state;
+	char *state_name;
+	char *s;
+	int err;
+
+	/* duplicate (as a null terminated string) */
+	state_name = kmalloc(count + 1, GFP_KERNEL);
+	if (state_name == NULL)
+		return -ENOMEM;
+	memcpy(state_name, buf, count);
+	state_name[count] = '\0';
+
+	/* and chop off newline */
+	s = strchr(state_name, '\n');
+	if (s != NULL)
+		*s = '\0';
+
+	/* try to select default state at first (if it exists) */
+	state = pinctrl_lookup_state(panel_mod->pinctrl, state_name);
+	if (!IS_ERR(state)) {
+		err = pinctrl_select_state(panel_mod->pinctrl, state);
+		if (err != 0)
+			dev_err(dev, "Failed to select state %s\n",
+					state_name);
+	} else {
+		dev_err(dev, "Failed to find state %s\n", state_name);
+		err = PTR_RET(state);
+	}
+
+	if (err == 0) {
+		kfree(panel_mod->selected_state_name);
+		panel_mod->selected_state_name = state_name;
+	}
+
+	return err ? err : count;
+}
+
+static DEVICE_ATTR(pinmux_state, S_IWUSR | S_IRUGO,
+		   pinmux_show_state, pinmux_store_state);
+
+static struct attribute *pinmux_attributes[] = {
+	&dev_attr_pinmux_state.attr,
+	NULL
+};
+
+static const struct attribute_group pinmux_attr_group = {
+	.attrs = pinmux_attributes,
+};
+
+static int panel_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = pdev->dev.of_node;
+	struct panel_module *panel_mod;
+	struct tilcdc_module *mod;
+	struct pinctrl_state *state;
+	enum of_gpio_flags ofgpioflags;
+	unsigned long gpioflags;
+	char *state_name;
+	int ret = -EINVAL;
+
+	/* bail out early if no DT data: */
+	if (!node) {
+		dev_err(&pdev->dev, "device-tree data is missing\n");
+		return -ENXIO;
+	}
+
+	panel_mod = kzalloc(sizeof(*panel_mod), GFP_KERNEL);
+	if (!panel_mod)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, panel_mod);
+
+	mod = &panel_mod->base;
+
+	tilcdc_module_init(mod, "panel", &panel_module_ops);
+
+	state_name = kmalloc(strlen(PINCTRL_STATE_DEFAULT) + 1,
+			GFP_KERNEL);
+	if (state_name == NULL) {
+		dev_err(dev, "Failed to allocate state name\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+	panel_mod->selected_state_name = state_name;
+	strcpy(panel_mod->selected_state_name, PINCTRL_STATE_DEFAULT);
+
+	panel_mod->pinctrl = devm_pinctrl_get(dev);
+	if (IS_ERR(panel_mod->pinctrl)) {
+		dev_err(dev, "Failed to get pinctrl\n");
+		ret = PTR_RET(panel_mod->pinctrl);
+		goto fail;
+	}
+
+	/* try to select default state at first (if it exists) */
+	state = pinctrl_lookup_state(panel_mod->pinctrl,
+			panel_mod->selected_state_name);
+	if (!IS_ERR(state)) {
+		ret = pinctrl_select_state(panel_mod->pinctrl, state);
+		if (ret != 0) {
+			dev_err(dev, "Failed to select default state\n");
+			goto fail;
+		}
+	} else {
+		panel_mod->selected_state_name = '\0';
+	}
+
+	/* Register sysfs hooks */
+	ret = sysfs_create_group(&dev->kobj, &pinmux_attr_group);
+	if (ret) {
+		dev_err(dev, "Failed to create sysfs group\n");
+		goto fail;
+	}
+
+	panel_mod->timings = of_get_display_timings(node);
+	if (!panel_mod->timings) {
+		dev_err(&pdev->dev, "could not get panel timings\n");
+		goto fail;
+	}
+
+	panel_mod->info = tilcdc_of_get_panel_info(node);
+	if (!panel_mod->info) {
+		dev_err(&pdev->dev, "could not get panel info\n");
+		goto fail;
+	}
+
+	panel_mod->backlight = of_find_backlight_by_node(node);
+	if (panel_mod->backlight)
+		dev_info(&pdev->dev, "found backlight\n");
+
+	panel_mod->gpio = of_get_named_gpio_flags(pdev->dev.of_node, "ti,power-gpio",
+                       0, &ofgpioflags);
+	if (IS_ERR_VALUE(panel_mod->gpio)) {
+		dev_warn(&pdev->dev, "panel: No power control GPIO\n");
+	} else {
+		gpioflags = GPIOF_DIR_OUT;
+		if (ofgpioflags & OF_GPIO_ACTIVE_LOW) {
+			gpioflags |= GPIOF_INIT_LOW;
+			dev_info(&pdev->dev, "Power GPIO active low, initial state set to low\n");
+		} else {
+			gpioflags |= GPIOF_INIT_HIGH;
+			dev_info(&pdev->dev, "Power GPIO active high, initial state set to high\n");
+		}
+		ret = devm_gpio_request_one(&pdev->dev, panel_mod->gpio,
+				gpioflags, "panel:PDN");
+		if (ret != 0) {
+			dev_err(&pdev->dev, "Failed to request power gpio\n");
+			goto fail;
+		}
+	}
+
+	return 0;
+
+fail:
+	panel_destroy(mod, NULL);
+	return ret;
+}
+
+static int panel_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct of_device_id panel_of_match[] = {
+		{ .compatible = "tilcdc,panel", },
+		{ },
+};
+MODULE_DEVICE_TABLE(of, panel_of_match);
+
+struct platform_driver panel_driver = {
+	.probe = panel_probe,
+	.remove = panel_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "panel",
+		.of_match_table = panel_of_match,
+	},
+};
+
+int __init tilcdc_panel_init(void)
+{
+	return platform_driver_register(&panel_driver);
+}
+
+void __exit tilcdc_panel_fini(void)
+{
+	platform_driver_unregister(&panel_driver);
+}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.h b/drivers/gpu/drm/tilcdc/tilcdc_panel.h
new file mode 100644
index 0000000..7db40aa
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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 __TILCDC_PANEL_H__
+#define __TILCDC_PANEL_H__
+
+/* sub-module for generic lcd panel output */
+
+int tilcdc_panel_init(void);
+void tilcdc_panel_fini(void);
+
+#endif /* __TILCDC_PANEL_H__ */
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h
new file mode 100644
index 0000000..1bf5e25
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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 __TILCDC_REGS_H__
+#define __TILCDC_REGS_H__
+
+/* LCDC register definitions, based on da8xx-fb */
+
+#include <linux/bitops.h>
+
+#include "tilcdc_drv.h"
+
+/* LCDC Status Register */
+#define LCDC_END_OF_FRAME1                       BIT(9)
+#define LCDC_END_OF_FRAME0                       BIT(8)
+#define LCDC_PL_LOAD_DONE                        BIT(6)
+#define LCDC_FIFO_UNDERFLOW                      BIT(5)
+#define LCDC_SYNC_LOST                           BIT(2)
+#define LCDC_FRAME_DONE                          BIT(0)
+
+/* LCDC DMA Control Register */
+#define LCDC_DMA_BURST_SIZE(x)                   ((x) << 4)
+#define LCDC_DMA_BURST_1                         0x0
+#define LCDC_DMA_BURST_2                         0x1
+#define LCDC_DMA_BURST_4                         0x2
+#define LCDC_DMA_BURST_8                         0x3
+#define LCDC_DMA_BURST_16                        0x4
+#define LCDC_V1_END_OF_FRAME_INT_ENA             BIT(2)
+#define LCDC_V2_END_OF_FRAME0_INT_ENA            BIT(8)
+#define LCDC_V2_END_OF_FRAME1_INT_ENA            BIT(9)
+#define LCDC_DUAL_FRAME_BUFFER_ENABLE            BIT(0)
+
+/* LCDC Control Register */
+#define LCDC_CLK_DIVISOR(x)                      ((x) << 8)
+#define LCDC_RASTER_MODE                         0x01
+
+/* LCDC Raster Control Register */
+#define LCDC_PALETTE_LOAD_MODE(x)                ((x) << 20)
+#define PALETTE_AND_DATA                         0x00
+#define PALETTE_ONLY                             0x01
+#define DATA_ONLY                                0x02
+
+#define LCDC_MONO_8BIT_MODE                      BIT(9)
+#define LCDC_RASTER_ORDER                        BIT(8)
+#define LCDC_TFT_MODE                            BIT(7)
+#define LCDC_V1_UNDERFLOW_INT_ENA                BIT(6)
+#define LCDC_V2_UNDERFLOW_INT_ENA                BIT(5)
+#define LCDC_V1_PL_INT_ENA                       BIT(4)
+#define LCDC_V2_PL_INT_ENA                       BIT(6)
+#define LCDC_MONOCHROME_MODE                     BIT(1)
+#define LCDC_RASTER_ENABLE                       BIT(0)
+#define LCDC_TFT_ALT_ENABLE                      BIT(23)
+#define LCDC_STN_565_ENABLE                      BIT(24)
+#define LCDC_V2_DMA_CLK_EN                       BIT(2)
+#define LCDC_V2_LIDD_CLK_EN                      BIT(1)
+#define LCDC_V2_CORE_CLK_EN                      BIT(0)
+#define LCDC_V2_LPP_B10                          26
+#define LCDC_V2_TFT_24BPP_MODE                   BIT(25)
+#define LCDC_V2_TFT_24BPP_UNPACK                 BIT(26)
+
+/* LCDC Raster Timing 2 Register */
+#define LCDC_AC_BIAS_TRANSITIONS_PER_INT(x)      ((x) << 16)
+#define LCDC_AC_BIAS_FREQUENCY(x)                ((x) << 8)
+#define LCDC_SYNC_CTRL                           BIT(25)
+#define LCDC_SYNC_EDGE                           BIT(24)
+#define LCDC_INVERT_PIXEL_CLOCK                  BIT(22)
+#define LCDC_INVERT_HSYNC                        BIT(21)
+#define LCDC_INVERT_VSYNC                        BIT(20)
+#define LCDC_LPP_B10                             BIT(26)
+
+/* LCDC Block */
+#define LCDC_PID_REG                             0x0
+#define LCDC_CTRL_REG                            0x4
+#define LCDC_STAT_REG                            0x8
+#define LCDC_RASTER_CTRL_REG                     0x28
+#define LCDC_RASTER_TIMING_0_REG                 0x2c
+#define LCDC_RASTER_TIMING_1_REG                 0x30
+#define LCDC_RASTER_TIMING_2_REG                 0x34
+#define LCDC_DMA_CTRL_REG                        0x40
+#define LCDC_DMA_FB_BASE_ADDR_0_REG              0x44
+#define LCDC_DMA_FB_CEILING_ADDR_0_REG           0x48
+#define LCDC_DMA_FB_BASE_ADDR_1_REG              0x4c
+#define LCDC_DMA_FB_CEILING_ADDR_1_REG           0x50
+
+/* Interrupt Registers available only in Version 2 */
+#define LCDC_RAW_STAT_REG                        0x58
+#define LCDC_MASKED_STAT_REG                     0x5c
+#define LCDC_INT_ENABLE_SET_REG                  0x60
+#define LCDC_INT_ENABLE_CLR_REG                  0x64
+#define LCDC_END_OF_INT_IND_REG                  0x68
+
+/* Clock registers available only on Version 2 */
+#define LCDC_CLK_ENABLE_REG                      0x6c
+#define LCDC_CLK_RESET_REG                       0x70
+#define LCDC_CLK_MAIN_RESET                      BIT(3)
+
+
+/*
+ * Helpers:
+ */
+
+static inline void tilcdc_write(struct drm_device *dev, u32 reg, u32 data)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	iowrite32(data, priv->mmio + reg);
+}
+
+static inline u32 tilcdc_read(struct drm_device *dev, u32 reg)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	return ioread32(priv->mmio + reg);
+}
+
+static inline void tilcdc_set(struct drm_device *dev, u32 reg, u32 mask)
+{
+	tilcdc_write(dev, reg, tilcdc_read(dev, reg) | mask);
+}
+
+static inline void tilcdc_clear(struct drm_device *dev, u32 reg, u32 mask)
+{
+	tilcdc_write(dev, reg, tilcdc_read(dev, reg) & ~mask);
+}
+
+/* the register to read/clear irqstatus differs between v1 and v2 of the IP */
+static inline u32 tilcdc_irqstatus_reg(struct drm_device *dev)
+{
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	return (priv->rev == 2) ? LCDC_MASKED_STAT_REG : LCDC_STAT_REG;
+}
+
+static inline u32 tilcdc_read_irqstatus(struct drm_device *dev)
+{
+	return tilcdc_read(dev, tilcdc_irqstatus_reg(dev));
+}
+
+static inline void tilcdc_clear_irqstatus(struct drm_device *dev, u32 mask)
+{
+	tilcdc_write(dev, tilcdc_irqstatus_reg(dev), mask);
+}
+
+#endif /* __TILCDC_REGS_H__ */
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
new file mode 100644
index 0000000..641aeee
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
@@ -0,0 +1,719 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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/i2c.h>
+#include <linux/of_i2c.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <drm/drm_encoder_slave.h>
+
+#include "tilcdc_drv.h"
+
+/* keep a list of text modestrings */
+struct slave_modelist {
+	struct list_head node;
+	const char *modestr;		/* the text mode string i.e. 1280x720@50 */
+	struct drm_cmdline_mode clmode;	/* the command line mode */
+	struct drm_display_mode *mode;	/* the display mode (as seen by the device) */
+	unsigned int parsed : 1;	/* parsed (whether good or bad) */
+	unsigned int good : 1;		/* it's ok to use it */
+};
+
+struct slave_module {
+	struct tilcdc_module base;
+	struct tilcdc_panel_info *info;
+	struct i2c_adapter *i2c;
+	struct pinctrl *pinctrl;
+	char *selected_state_name;
+
+	struct list_head whitelist;
+	struct list_head blacklist;
+};
+#define to_slave_module(x) container_of(x, struct slave_module, base)
+
+/*
+ * Encoder:
+ */
+
+struct slave_encoder {
+	struct drm_encoder_slave base;
+	struct slave_module *mod;
+};
+#define to_slave_encoder(x) container_of(to_encoder_slave(x), struct slave_encoder, base)
+
+static inline struct drm_encoder_slave_funcs *
+get_slave_funcs(struct drm_encoder *enc)
+{
+	return to_encoder_slave(enc)->slave_funcs;
+}
+
+static void slave_encoder_destroy(struct drm_encoder *encoder)
+{
+	struct slave_encoder *slave_encoder = to_slave_encoder(encoder);
+	if (get_slave_funcs(encoder))
+		get_slave_funcs(encoder)->destroy(encoder);
+	drm_encoder_cleanup(encoder);
+	kfree(slave_encoder);
+}
+
+static void slave_encoder_prepare(struct drm_encoder *encoder)
+{
+	struct slave_encoder *slave_encoder = to_slave_encoder(encoder);
+
+	drm_i2c_encoder_prepare(encoder);
+	tilcdc_crtc_set_panel_info(encoder->crtc, slave_encoder->mod->info);
+}
+
+static const struct drm_encoder_funcs slave_encoder_funcs = {
+		.destroy        = slave_encoder_destroy,
+};
+
+static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = {
+		.dpms           = drm_i2c_encoder_dpms,
+		.mode_fixup     = drm_i2c_encoder_mode_fixup,
+		.prepare        = slave_encoder_prepare,
+		.commit         = drm_i2c_encoder_commit,
+		.mode_set       = drm_i2c_encoder_mode_set,
+		.save           = drm_i2c_encoder_save,
+		.restore        = drm_i2c_encoder_restore,
+};
+
+static const struct i2c_board_info info = {
+		I2C_BOARD_INFO("tda998x", 0x70)
+};
+
+static struct drm_encoder *slave_encoder_create(struct drm_device *dev,
+		struct slave_module *mod)
+{
+	struct slave_encoder *slave_encoder;
+	struct drm_encoder *encoder;
+	int ret;
+
+	slave_encoder = kzalloc(sizeof(*slave_encoder), GFP_KERNEL);
+	if (!slave_encoder) {
+		dev_err(dev->dev, "allocation failed\n");
+		return NULL;
+	}
+
+	slave_encoder->mod = mod;
+
+	encoder = &slave_encoder->base.base;
+	encoder->possible_crtcs = 1;
+
+	ret = drm_encoder_init(dev, encoder, &slave_encoder_funcs,
+			DRM_MODE_ENCODER_TMDS);
+	if (ret)
+		goto fail;
+
+	drm_encoder_helper_add(encoder, &slave_encoder_helper_funcs);
+
+	ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), mod->i2c, &info);
+	if (ret)
+		goto fail;
+
+	return encoder;
+
+fail:
+	slave_encoder_destroy(encoder);
+	return NULL;
+}
+
+/*
+ * Connector:
+ */
+
+struct slave_connector {
+	struct drm_connector base;
+
+	struct drm_encoder *encoder;  /* our connected encoder */
+	struct slave_module *mod;
+};
+#define to_slave_connector(x) container_of(x, struct slave_connector, base)
+
+static void slave_connector_destroy(struct drm_connector *connector)
+{
+	struct slave_connector *slave_connector = to_slave_connector(connector);
+	drm_connector_cleanup(connector);
+	kfree(slave_connector);
+}
+
+static enum drm_connector_status slave_connector_detect(
+		struct drm_connector *connector,
+		bool force)
+{
+	struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
+	return get_slave_funcs(encoder)->detect(encoder, connector);
+}
+
+static int slave_connector_get_modes(struct drm_connector *connector)
+{
+	struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
+	return get_slave_funcs(encoder)->get_modes(encoder, connector);
+}
+
+static int slave_modelist_match(struct drm_connector *connector,
+		struct slave_modelist *sml, struct drm_display_mode *mode)
+{
+	struct drm_cmdline_mode *clmode = &sml->clmode;
+
+	if (sml->mode == NULL || !sml->good)
+		return 0;
+
+	/* xres, yres valid */
+	if (clmode->specified &&
+		(drm_mode_width(mode) != clmode->xres ||
+			drm_mode_height(mode) != clmode->yres))
+		return 0;
+
+	/* refresh mode specified */
+	if (clmode->refresh_specified &&
+		drm_mode_vrefresh(mode) != clmode->refresh)
+		return 0;
+
+	/* interlace */
+	if (clmode->interlace && (mode->flags & DRM_MODE_FLAG_INTERLACE) == 0)
+		return 0;
+
+	/* match */
+	return 1;
+}
+
+/* returns 0 if mode is listed, -ENOENT otherwise */
+static int slave_connector_mode_match(struct drm_connector *connector,
+		struct drm_display_mode *mode,
+		struct list_head *lh)
+{
+	struct drm_device *dev = connector->dev;
+	struct slave_modelist *sml;
+	bool parse;
+
+	/* ok, we have to find a match */
+	list_for_each_entry(sml, lh, node) {
+
+		/* if the mode is not parsed, do it now */
+		if (!sml->parsed) {
+
+			/* whether good or bad, we're trying only once */
+			sml->parsed = 1;
+			sml->good = 0;
+
+			parse = drm_mode_parse_command_line_for_connector(
+					sml->modestr, connector, &sml->clmode);
+
+			/* report in case something's off */
+			if (!parse) {
+				dev_err(dev->dev, "Failed to parse mode %s\n",
+						sml->modestr);
+				continue;
+			}
+
+			/* need to hold the mutex */
+			mutex_lock(&dev->mode_config.mutex);
+			sml->mode = drm_mode_create_from_cmdline_mode(dev,
+					&sml->clmode);
+			mutex_unlock(&dev->mode_config.mutex);
+
+			if (sml->mode == NULL) {
+				dev_err(dev->dev, "Failed to create mode %s\n",
+						sml->modestr);
+				continue;
+			}
+			sml->good = 1;
+		}
+
+		/* bad mode is skipped */
+		if (!sml->good)
+			continue;
+
+		/* we can't use drm_mode_equal, we use own own comparison */
+		if (slave_modelist_match(connector, sml, mode)) {
+			return 1;
+		}
+
+	}
+
+	return 0;
+}
+
+static int slave_connector_mode_whitelisted(struct drm_connector *connector,
+		struct drm_display_mode *mode)
+{
+	struct slave_connector *slave_connector = to_slave_connector(connector);
+	struct slave_module *slave_mod = slave_connector->mod;
+	int ret;
+
+	/* if the list is empty, everything is whitelisted */
+	if (list_empty(&slave_mod->whitelist))
+		return 1;
+
+	ret = slave_connector_mode_match(connector, mode, &slave_mod->whitelist);
+	if (ret != 0)
+		return 1;
+
+	/* not found */
+	return 0;
+}
+
+static int slave_connector_mode_blacklisted(struct drm_connector *connector,
+		struct drm_display_mode *mode)
+{
+	struct slave_connector *slave_connector = to_slave_connector(connector);
+	struct slave_module *slave_mod = slave_connector->mod;
+	int ret;
+
+	/* if the list is empty, nothing is blacklisted */
+	if (list_empty(&slave_mod->blacklist))
+		return 0;
+
+	ret = slave_connector_mode_match(connector, mode, &slave_mod->blacklist);
+	if (ret != 0)
+		return 1;
+
+	/* not found; all is OK */
+	return 0;
+}
+
+static int slave_connector_mode_valid(struct drm_connector *connector,
+		  struct drm_display_mode *mode)
+{
+	struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
+	struct drm_device *dev = connector->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	int ret;
+
+	/* if there's a whitelist, we must be in it */
+	if (!slave_connector_mode_whitelisted(connector, mode)) {
+		dev_info(dev->dev, "mode %dx%d@%d is not whitelisted\n",
+			drm_mode_width(mode), drm_mode_height(mode),
+			drm_mode_vrefresh(mode));
+		return MODE_BAD;
+	}
+
+	/* if there's a blacklist, we shouldn't be in it */
+	if (slave_connector_mode_blacklisted(connector, mode)) {
+		dev_info(dev->dev, "mode %dx%d@%d is blacklisted\n",
+			drm_mode_width(mode), drm_mode_height(mode),
+			drm_mode_vrefresh(mode));
+		return MODE_BAD;
+	}
+
+	ret = tilcdc_crtc_mode_valid(priv->crtc, mode,
+			priv->allow_non_rblank ? 0 : 1,
+			priv->allow_non_audio ? 0 : 1,
+			connector->edid_blob_ptr ?
+				(struct edid *)connector->edid_blob_ptr->data :
+				NULL);
+	if (ret != MODE_OK)
+		return ret;
+
+	return get_slave_funcs(encoder)->mode_valid(encoder, mode);
+}
+
+static struct drm_encoder *slave_connector_best_encoder(
+		struct drm_connector *connector)
+{
+	struct slave_connector *slave_connector = to_slave_connector(connector);
+	return slave_connector->encoder;
+}
+
+static int slave_connector_set_property(struct drm_connector *connector,
+		struct drm_property *property, uint64_t value)
+{
+	struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
+	return get_slave_funcs(encoder)->set_property(encoder,
+			connector, property, value);
+}
+
+static const struct drm_connector_funcs slave_connector_funcs = {
+	.destroy            = slave_connector_destroy,
+	.dpms               = drm_helper_connector_dpms,
+	.detect             = slave_connector_detect,
+	.fill_modes         = drm_helper_probe_single_connector_modes,
+	.set_property       = slave_connector_set_property,
+};
+
+static const struct drm_connector_helper_funcs slave_connector_helper_funcs = {
+	.get_modes          = slave_connector_get_modes,
+	.mode_valid         = slave_connector_mode_valid,
+	.best_encoder       = slave_connector_best_encoder,
+};
+
+static struct drm_connector *slave_connector_create(struct drm_device *dev,
+		struct slave_module *mod, struct drm_encoder *encoder)
+{
+	struct slave_connector *slave_connector;
+	struct drm_connector *connector;
+	int ret;
+
+	slave_connector = kzalloc(sizeof(*slave_connector), GFP_KERNEL);
+	if (!slave_connector) {
+		dev_err(dev->dev, "allocation failed\n");
+		return NULL;
+	}
+
+	slave_connector->encoder = encoder;
+	slave_connector->mod = mod;
+
+	connector = &slave_connector->base;
+
+	drm_connector_init(dev, connector, &slave_connector_funcs,
+			DRM_MODE_CONNECTOR_HDMIA);
+	drm_connector_helper_add(connector, &slave_connector_helper_funcs);
+
+	connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+			DRM_CONNECTOR_POLL_DISCONNECT;
+
+	connector->interlace_allowed = 0;
+	connector->doublescan_allowed = 0;
+
+	get_slave_funcs(encoder)->create_resources(encoder, connector);
+
+	ret = drm_mode_connector_attach_encoder(connector, encoder);
+	if (ret)
+		goto fail;
+
+	drm_sysfs_connector_add(connector);
+
+	return connector;
+
+fail:
+	slave_connector_destroy(connector);
+	return NULL;
+}
+
+/*
+ * Module:
+ */
+
+static int slave_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
+{
+	struct slave_module *slave_mod = to_slave_module(mod);
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+
+	if (priv->num_encoders >= ARRAY_SIZE(priv->encoders))
+		return -ENOENT;
+
+	if (priv->num_connectors >= ARRAY_SIZE(priv->connectors))
+		return -ENOENT;
+
+	encoder = slave_encoder_create(dev, slave_mod);
+	if (!encoder)
+		return -ENOMEM;
+
+	connector = slave_connector_create(dev, slave_mod, encoder);
+	if (!connector)
+		return -ENOMEM;
+
+	priv->encoders[priv->num_encoders++] = encoder;
+	priv->connectors[priv->num_connectors++] = connector;
+
+	return 0;
+}
+
+static void slave_destroy(struct tilcdc_module *mod, struct drm_device *dev)
+{
+	struct slave_module *slave_mod = to_slave_module(mod);
+	struct slave_modelist *sml;
+
+	tilcdc_module_cleanup(mod);
+
+	if (dev != NULL) {
+		/* no need to free sml, it's res tracked */
+		list_for_each_entry(sml, &slave_mod->whitelist, node) {
+			if (sml->mode != NULL)
+				drm_mode_destroy(dev, sml->mode);
+		}
+
+		list_for_each_entry(sml, &slave_mod->whitelist, node) {
+			if (sml->mode != NULL)
+				drm_mode_destroy(dev, sml->mode);
+		}
+	}
+
+	kfree(slave_mod->info);
+	kfree(slave_mod);
+}
+
+static const struct tilcdc_module_ops slave_module_ops = {
+	.modeset_init = slave_modeset_init,
+	.destroy = slave_destroy,
+};
+
+/*
+ * Device:
+ */
+
+static struct of_device_id slave_of_match[];
+
+static ssize_t pinmux_show_state(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct slave_module *slave_mod = platform_get_drvdata(pdev);
+	const char *name;
+
+	name = slave_mod->selected_state_name;
+	if (name == NULL || strlen(name) == 0)
+		name = "none";
+	return sprintf(buf, "%s\n", name);
+}
+
+static ssize_t pinmux_store_state(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct slave_module *slave_mod = platform_get_drvdata(pdev);
+	struct pinctrl_state *state;
+	char *state_name;
+	char *s;
+	int err;
+
+	/* duplicate (as a null terminated string) */
+	state_name = kmalloc(count + 1, GFP_KERNEL);
+	if (state_name == NULL)
+		return -ENOMEM;
+	memcpy(state_name, buf, count);
+	state_name[count] = '\0';
+
+	/* and chop off newline */
+	s = strchr(state_name, '\n');
+	if (s != NULL)
+		*s = '\0';
+
+	/* try to select default state at first (if it exists) */
+	state = pinctrl_lookup_state(slave_mod->pinctrl, state_name);
+	if (!IS_ERR(state)) {
+		err = pinctrl_select_state(slave_mod->pinctrl, state);
+		if (err != 0)
+			dev_err(dev, "Failed to select state %s\n",
+					state_name);
+	} else {
+		dev_err(dev, "Failed to find state %s\n", state_name);
+		err = PTR_RET(state);
+	}
+
+	if (err == 0) {
+		kfree(slave_mod->selected_state_name);
+		slave_mod->selected_state_name = state_name;
+	}
+
+	return err ? err : count;
+}
+
+static DEVICE_ATTR(pinmux_state, S_IWUSR | S_IRUGO,
+		   pinmux_show_state, pinmux_store_state);
+
+static struct attribute *pinmux_attributes[] = {
+	&dev_attr_pinmux_state.attr,
+	NULL
+};
+
+static const struct attribute_group pinmux_attr_group = {
+	.attrs = pinmux_attributes,
+};
+
+/* fill in the mode list via the string list property */
+static int slave_mode_of_mode_list(struct platform_device *pdev,
+		const char *propname, struct list_head *lh)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct slave_modelist *sml;
+	int ret, i, count;
+
+	/* count the string list property */
+	count = of_property_count_strings(node, propname);
+
+	/* negative or zero, means no mode list */
+	if (count <= 0)
+		return 0;
+
+	for (i = 0; i < count; i++) {
+
+		sml = devm_kzalloc(dev, sizeof(*sml), GFP_KERNEL);
+		if (sml == NULL) {
+			dev_err(dev, "Failed to allocate mode list for %s\n",
+					propname);
+			return -ENOMEM;
+		}
+
+		ret = of_property_read_string_index(node, propname, i,
+				&sml->modestr);
+		if (ret != 0) {
+			dev_err(dev, "Failed to read string #%d for %s \n",
+					i, propname);
+			return ret;
+		}
+
+		/* add it to the tail */
+		list_add_tail(&sml->node, lh);
+
+		dev_info(dev, "%s #%d -> %s\n",
+				propname, i, sml->modestr);
+
+	}
+
+	return 0;
+}
+
+static int slave_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct device_node *i2c_node;
+	struct slave_module *slave_mod;
+	struct tilcdc_module *mod;
+	struct pinctrl_state *state;
+	uint32_t i2c_phandle;
+	char *state_name;
+	int ret = -EINVAL;
+
+	/* bail out early if no DT data: */
+	if (!node) {
+		dev_err(&pdev->dev, "device-tree data is missing\n");
+		return -ENXIO;
+	}
+
+	slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL);
+	if (!slave_mod)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, slave_mod);
+
+	INIT_LIST_HEAD(&slave_mod->whitelist);
+	INIT_LIST_HEAD(&slave_mod->blacklist);
+
+	mod = &slave_mod->base;
+
+	tilcdc_module_init(mod, "slave", &slave_module_ops);
+
+	state_name = kmalloc(strlen(PINCTRL_STATE_DEFAULT) + 1,
+			GFP_KERNEL);
+	if (state_name == NULL) {
+		dev_err(dev, "Failed to allocate state name\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+	slave_mod->selected_state_name = state_name;
+	strcpy(slave_mod->selected_state_name, PINCTRL_STATE_DEFAULT);
+
+	slave_mod->pinctrl = devm_pinctrl_get(dev);
+	if (IS_ERR(slave_mod->pinctrl)) {
+		ret = PTR_RET(slave_mod->pinctrl);
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "Failed to get pinctrl\n");
+		goto fail;
+	}
+
+	/* try to select default state at first (if it exists) */
+	state = pinctrl_lookup_state(slave_mod->pinctrl,
+			slave_mod->selected_state_name);
+	if (!IS_ERR(state)) {
+		ret = pinctrl_select_state(slave_mod->pinctrl, state);
+		if (ret != 0) {
+			dev_err(dev, "Failed to select default state\n");
+			goto fail;
+		}
+	} else {
+		slave_mod->selected_state_name = '\0';
+	}
+
+	/* Register sysfs hooks */
+	ret = sysfs_create_group(&dev->kobj, &pinmux_attr_group);
+	if (ret) {
+		dev_err(dev, "Failed to create sysfs group\n");
+		goto fail;
+	}
+
+	if (of_property_read_u32(node, "i2c", &i2c_phandle)) {
+		dev_err(&pdev->dev, "could not get i2c bus phandle\n");
+		goto fail;
+	}
+
+	i2c_node = of_find_node_by_phandle(i2c_phandle);
+	if (!i2c_node) {
+		dev_err(&pdev->dev, "could not get i2c bus node\n");
+		goto fail;
+	}
+
+	slave_mod->i2c = of_find_i2c_adapter_by_node(i2c_node);
+	if (!slave_mod->i2c) {
+		dev_err(&pdev->dev, "could not get i2c\n");
+		goto fail;
+	}
+
+	slave_mod->info = tilcdc_of_get_panel_info(node);
+	if (!slave_mod->info) {
+		dev_err(&pdev->dev, "could not get panel info\n");
+		goto fail;
+	}
+
+	ret = slave_mode_of_mode_list(pdev, "modes-blacklisted",
+			&slave_mod->blacklist);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "Invalid modes-blacklisted property\n");
+		goto fail;
+	}
+
+	ret = slave_mode_of_mode_list(pdev, "modes-whitelisted",
+			&slave_mod->whitelist);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "Invalid modes-whitelisted property\n");
+		goto fail;
+	}
+
+	of_node_put(i2c_node);
+
+	return 0;
+
+fail:
+	slave_destroy(mod, NULL);
+	return ret;
+}
+
+static int slave_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct of_device_id slave_of_match[] = {
+		{ .compatible = "tilcdc,slave", },
+		{ },
+};
+MODULE_DEVICE_TABLE(of, slave_of_match);
+
+struct platform_driver slave_driver = {
+	.probe = slave_probe,
+	.remove = slave_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "slave",
+		.of_match_table = slave_of_match,
+	},
+};
+
+int __init tilcdc_slave_init(void)
+{
+	return platform_driver_register(&slave_driver);
+}
+
+void __exit tilcdc_slave_fini(void)
+{
+	platform_driver_unregister(&slave_driver);
+}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.h b/drivers/gpu/drm/tilcdc/tilcdc_slave.h
new file mode 100644
index 0000000..2f85048
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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 __TILCDC_SLAVE_H__
+#define __TILCDC_SLAVE_H__
+
+/* sub-module for i2c slave encoder output */
+
+int tilcdc_slave_init(void);
+void tilcdc_slave_fini(void);
+
+#endif /* __TILCDC_SLAVE_H__ */
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
new file mode 100644
index 0000000..86fcd1c
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
@@ -0,0 +1,543 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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/i2c.h>
+#include <linux/of_i2c.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+
+#include "tilcdc_drv.h"
+
+struct tfp410_module {
+	struct tilcdc_module base;
+	struct i2c_adapter *i2c;
+	enum of_gpio_flags ofgpioflags;
+	int gpio;
+	struct pinctrl *pinctrl;
+	char *selected_state_name;
+};
+#define to_tfp410_module(x) container_of(x, struct tfp410_module, base)
+
+
+static const struct tilcdc_panel_info dvi_info = {
+		.ac_bias                = 255,
+		.ac_bias_intrpt         = 0,
+		.dma_burst_sz           = 16,
+		.bpp                    = 16,
+		.fdd                    = 0x80,
+		.tft_alt_mode           = 0,
+		.sync_edge              = 0,
+		.sync_ctrl              = 1,
+		.raster_order           = 0,
+};
+
+/*
+ * Encoder:
+ */
+
+struct tfp410_encoder {
+	struct drm_encoder base;
+	struct tfp410_module *mod;
+	int dpms;
+};
+#define to_tfp410_encoder(x) container_of(x, struct tfp410_encoder, base)
+
+
+static void tfp410_encoder_destroy(struct drm_encoder *encoder)
+{
+	struct tfp410_encoder *tfp410_encoder = to_tfp410_encoder(encoder);
+	drm_encoder_cleanup(encoder);
+	kfree(tfp410_encoder);
+}
+
+static void tfp410_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct tfp410_encoder *tfp410_encoder = to_tfp410_encoder(encoder);
+	int state;
+
+	if (tfp410_encoder->dpms == mode)
+		return;
+
+	if (IS_ERR_VALUE(tfp410_encoder->mod->gpio))
+		return;
+
+	state = mode == DRM_MODE_DPMS_ON;
+	if (tfp410_encoder->mod->ofgpioflags & OF_GPIO_ACTIVE_LOW)
+		state = !state;
+
+	pr_debug("%s: dpms %d, gpio-state %d\n", __func__,
+			mode == DRM_MODE_DPMS_ON, state);
+
+	gpio_direction_output(tfp410_encoder->mod->gpio, state);
+
+	tfp410_encoder->dpms = mode;
+}
+
+static bool tfp410_encoder_mode_fixup(struct drm_encoder *encoder,
+		const struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	/* nothing needed */
+	return true;
+}
+
+static void tfp410_encoder_prepare(struct drm_encoder *encoder)
+{
+	tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+	tilcdc_crtc_set_panel_info(encoder->crtc, &dvi_info);
+}
+
+static void tfp410_encoder_commit(struct drm_encoder *encoder)
+{
+	tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static void tfp410_encoder_mode_set(struct drm_encoder *encoder,
+		struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	/* nothing needed */
+}
+
+static const struct drm_encoder_funcs tfp410_encoder_funcs = {
+		.destroy        = tfp410_encoder_destroy,
+};
+
+static const struct drm_encoder_helper_funcs tfp410_encoder_helper_funcs = {
+		.dpms           = tfp410_encoder_dpms,
+		.mode_fixup     = tfp410_encoder_mode_fixup,
+		.prepare        = tfp410_encoder_prepare,
+		.commit         = tfp410_encoder_commit,
+		.mode_set       = tfp410_encoder_mode_set,
+};
+
+static struct drm_encoder *tfp410_encoder_create(struct drm_device *dev,
+		struct tfp410_module *mod)
+{
+	struct tfp410_encoder *tfp410_encoder;
+	struct drm_encoder *encoder;
+	int ret;
+
+	tfp410_encoder = kzalloc(sizeof(*tfp410_encoder), GFP_KERNEL);
+	if (!tfp410_encoder) {
+		dev_err(dev->dev, "allocation failed\n");
+		return NULL;
+	}
+
+	tfp410_encoder->dpms = DRM_MODE_DPMS_OFF;
+	tfp410_encoder->mod = mod;
+
+	encoder = &tfp410_encoder->base;
+	encoder->possible_crtcs = 1;
+
+	ret = drm_encoder_init(dev, encoder, &tfp410_encoder_funcs,
+			DRM_MODE_ENCODER_TMDS);
+	if (ret < 0)
+		goto fail;
+
+	drm_encoder_helper_add(encoder, &tfp410_encoder_helper_funcs);
+
+	return encoder;
+
+fail:
+	tfp410_encoder_destroy(encoder);
+	return NULL;
+}
+
+/*
+ * Connector:
+ */
+
+struct tfp410_connector {
+	struct drm_connector base;
+
+	struct drm_encoder *encoder;  /* our connected encoder */
+	struct tfp410_module *mod;
+};
+#define to_tfp410_connector(x) container_of(x, struct tfp410_connector, base)
+
+
+static void tfp410_connector_destroy(struct drm_connector *connector)
+{
+	struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
+	drm_connector_cleanup(connector);
+	kfree(tfp410_connector);
+}
+
+static enum drm_connector_status tfp410_connector_detect(
+		struct drm_connector *connector,
+		bool force)
+{
+	struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
+
+	if (drm_probe_ddc(tfp410_connector->mod->i2c))
+		return connector_status_connected;
+
+	return connector_status_unknown;
+}
+
+static int tfp410_connector_get_modes(struct drm_connector *connector)
+{
+	struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
+	struct edid *edid;
+	int ret = 0;
+
+	edid = drm_get_edid(connector, tfp410_connector->mod->i2c);
+
+	drm_mode_connector_update_edid_property(connector, edid);
+
+	if (edid) {
+		ret = drm_add_edid_modes(connector, edid);
+		kfree(edid);
+	}
+
+	return ret;
+}
+
+static int tfp410_connector_mode_valid(struct drm_connector *connector,
+		  struct drm_display_mode *mode)
+{
+	struct tilcdc_drm_private *priv = connector->dev->dev_private;
+	/* our only constraints are what the crtc can generate: */
+	return tilcdc_crtc_mode_valid(priv->crtc, mode,
+			priv->allow_non_rblank ? 0 : 1, 0, NULL);
+}
+
+static struct drm_encoder *tfp410_connector_best_encoder(
+		struct drm_connector *connector)
+{
+	struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
+	return tfp410_connector->encoder;
+}
+
+static const struct drm_connector_funcs tfp410_connector_funcs = {
+	.destroy            = tfp410_connector_destroy,
+	.dpms               = drm_helper_connector_dpms,
+	.detect             = tfp410_connector_detect,
+	.fill_modes         = drm_helper_probe_single_connector_modes,
+};
+
+static const struct drm_connector_helper_funcs tfp410_connector_helper_funcs = {
+	.get_modes          = tfp410_connector_get_modes,
+	.mode_valid         = tfp410_connector_mode_valid,
+	.best_encoder       = tfp410_connector_best_encoder,
+};
+
+static struct drm_connector *tfp410_connector_create(struct drm_device *dev,
+		struct tfp410_module *mod, struct drm_encoder *encoder)
+{
+	struct tfp410_connector *tfp410_connector;
+	struct drm_connector *connector;
+	int ret;
+
+	tfp410_connector = kzalloc(sizeof(*tfp410_connector), GFP_KERNEL);
+	if (!tfp410_connector) {
+		dev_err(dev->dev, "allocation failed\n");
+		return NULL;
+	}
+
+	tfp410_connector->encoder = encoder;
+	tfp410_connector->mod = mod;
+
+	connector = &tfp410_connector->base;
+
+	drm_connector_init(dev, connector, &tfp410_connector_funcs,
+			DRM_MODE_CONNECTOR_DVID);
+	drm_connector_helper_add(connector, &tfp410_connector_helper_funcs);
+
+	connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+			DRM_CONNECTOR_POLL_DISCONNECT;
+
+	connector->interlace_allowed = 0;
+	connector->doublescan_allowed = 0;
+
+	ret = drm_mode_connector_attach_encoder(connector, encoder);
+	if (ret)
+		goto fail;
+
+	drm_sysfs_connector_add(connector);
+
+	return connector;
+
+fail:
+	tfp410_connector_destroy(connector);
+	return NULL;
+}
+
+/*
+ * Module:
+ */
+
+static int tfp410_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
+{
+	struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+
+	encoder = tfp410_encoder_create(dev, tfp410_mod);
+	if (!encoder)
+		return -ENOMEM;
+
+	connector = tfp410_connector_create(dev, tfp410_mod, encoder);
+	if (!connector)
+		return -ENOMEM;
+
+	priv->encoders[priv->num_encoders++] = encoder;
+	priv->connectors[priv->num_connectors++] = connector;
+
+	return 0;
+}
+
+static void tfp410_destroy(struct tilcdc_module *mod, struct drm_device *dev)
+{
+	struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
+
+	if (tfp410_mod->i2c)
+		i2c_put_adapter(tfp410_mod->i2c);
+
+	if (!IS_ERR_VALUE(tfp410_mod->gpio))
+		gpio_free(tfp410_mod->gpio);
+
+	tilcdc_module_cleanup(mod);
+	kfree(tfp410_mod);
+}
+
+static const struct tilcdc_module_ops tfp410_module_ops = {
+		.modeset_init = tfp410_modeset_init,
+		.destroy = tfp410_destroy,
+};
+
+/*
+ * Device:
+ */
+
+static struct of_device_id tfp410_of_match[];
+
+static ssize_t pinmux_show_state(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct tfp410_module *tfp410_mod = platform_get_drvdata(pdev);
+	const char *name;
+
+	name = tfp410_mod->selected_state_name;
+	if (name == NULL || strlen(name) == 0)
+		name = "none";
+	return sprintf(buf, "%s\n", name);
+}
+
+static ssize_t pinmux_store_state(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct tfp410_module *tfp410_mod = platform_get_drvdata(pdev);
+	struct pinctrl_state *state;
+	char *state_name;
+	char *s;
+	int err;
+
+	/* duplicate (as a null terminated string) */
+	state_name = kmalloc(count + 1, GFP_KERNEL);
+	if (state_name == NULL)
+		return -ENOMEM;
+	memcpy(state_name, buf, count);
+	state_name[count] = '\0';
+
+	/* and chop off newline */
+	s = strchr(state_name, '\n');
+	if (s != NULL)
+		*s = '\0';
+
+	/* try to select default state at first (if it exists) */
+	state = pinctrl_lookup_state(tfp410_mod->pinctrl, state_name);
+	if (!IS_ERR(state)) {
+		err = pinctrl_select_state(tfp410_mod->pinctrl, state);
+		if (err != 0)
+			dev_err(dev, "Failed to select state %s\n",
+					state_name);
+	} else {
+		dev_err(dev, "Failed to find state %s\n", state_name);
+		err = PTR_RET(state);
+	}
+
+	if (err == 0) {
+		kfree(tfp410_mod->selected_state_name);
+		tfp410_mod->selected_state_name = state_name;
+	}
+
+	return err ? err : count;
+}
+
+static DEVICE_ATTR(pinmux_state, S_IWUSR | S_IRUGO,
+		   pinmux_show_state, pinmux_store_state);
+
+static struct attribute *pinmux_attributes[] = {
+	&dev_attr_pinmux_state.attr,
+	NULL
+};
+
+static const struct attribute_group pinmux_attr_group = {
+	.attrs = pinmux_attributes,
+};
+
+static int tfp410_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = pdev->dev.of_node;
+	struct device_node *i2c_node;
+	struct tfp410_module *tfp410_mod;
+	struct tilcdc_module *mod;
+	struct pinctrl_state *state;
+	uint32_t i2c_phandle;
+	unsigned long gpioflags;
+	char *state_name;
+	int ret = -EINVAL;
+
+	/* bail out early if no DT data: */
+	if (!node) {
+		dev_err(&pdev->dev, "device-tree data is missing\n");
+		return -ENXIO;
+	}
+
+	tfp410_mod = kzalloc(sizeof(*tfp410_mod), GFP_KERNEL);
+	if (!tfp410_mod)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, tfp410_mod);
+
+	mod = &tfp410_mod->base;
+
+	tilcdc_module_init(mod, "tfp410", &tfp410_module_ops);
+
+	state_name = kmalloc(strlen(PINCTRL_STATE_DEFAULT) + 1,
+			GFP_KERNEL);
+	if (state_name == NULL) {
+		dev_err(dev, "Failed to allocate state name\n");
+		ret = -ENOMEM;
+		goto fail;
+	}
+	tfp410_mod->selected_state_name = state_name;
+	strcpy(tfp410_mod->selected_state_name, PINCTRL_STATE_DEFAULT);
+
+	tfp410_mod->pinctrl = devm_pinctrl_get(dev);
+	if (IS_ERR(tfp410_mod->pinctrl)) {
+		dev_err(dev, "Failed to get pinctrl\n");
+		ret = PTR_RET(tfp410_mod->pinctrl);
+		goto fail;
+	}
+
+	/* try to select default state at first (if it exists) */
+	state = pinctrl_lookup_state(tfp410_mod->pinctrl,
+			tfp410_mod->selected_state_name);
+	if (!IS_ERR(state)) {
+		ret = pinctrl_select_state(tfp410_mod->pinctrl, state);
+		if (ret != 0) {
+			dev_err(dev, "Failed to select default state\n");
+			goto fail;
+		}
+	} else {
+		tfp410_mod->selected_state_name = '\0';
+	}
+
+	/* Register sysfs hooks */
+	ret = sysfs_create_group(&dev->kobj, &pinmux_attr_group);
+	if (ret) {
+		dev_err(dev, "Failed to create sysfs group\n");
+		goto fail;
+	}
+
+
+	if (of_property_read_u32(node, "i2c", &i2c_phandle)) {
+		dev_err(&pdev->dev, "could not get i2c bus phandle\n");
+		goto fail;
+	}
+
+	i2c_node = of_find_node_by_phandle(i2c_phandle);
+	if (!i2c_node) {
+		dev_err(&pdev->dev, "could not get i2c bus node\n");
+		goto fail;
+	}
+
+	tfp410_mod->i2c = of_find_i2c_adapter_by_node(i2c_node);
+	if (!tfp410_mod->i2c) {
+		dev_err(&pdev->dev, "could not get i2c\n");
+		goto fail;
+	}
+
+	of_node_put(i2c_node);
+
+	tfp410_mod->gpio = of_get_named_gpio_flags(pdev->dev.of_node, "ti,power-gpio",
+                       0, &tfp410_mod->ofgpioflags);
+	if (IS_ERR_VALUE(tfp410_mod->gpio)) {
+		dev_warn(&pdev->dev, "tftp410: No power control GPIO\n");
+	} else {
+		gpioflags = GPIOF_DIR_OUT;
+		if (tfp410_mod->ofgpioflags & OF_GPIO_ACTIVE_LOW) {
+			gpioflags |= GPIOF_INIT_LOW;
+			dev_info(&pdev->dev, "Power GPIO active low, initial state set to low\n");
+		} else {
+			gpioflags |= GPIOF_INIT_HIGH;
+			dev_info(&pdev->dev, "Power GPIO active high, initial state set to high\n");
+		}
+		ret = devm_gpio_request_one(&pdev->dev, tfp410_mod->gpio,
+				gpioflags, "tfp410:PDN");
+		if (ret != 0) {
+			dev_err(&pdev->dev, "Failed to request power gpio\n");
+			goto fail;
+		}
+	}
+
+	return 0;
+
+fail:
+	tfp410_destroy(mod, NULL);	/* meh */
+	return ret;
+}
+
+static int tfp410_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct of_device_id tfp410_of_match[] = {
+		{ .compatible = "tilcdc,tfp410", },
+		{ },
+};
+MODULE_DEVICE_TABLE(of, tfp410_of_match);
+
+struct platform_driver tfp410_driver = {
+	.probe = tfp410_probe,
+	.remove = tfp410_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "tfp410",
+		.of_match_table = tfp410_of_match,
+	},
+};
+
+int __init tilcdc_tfp410_init(void)
+{
+	return platform_driver_register(&tfp410_driver);
+}
+
+void __exit tilcdc_tfp410_fini(void)
+{
+	platform_driver_unregister(&tfp410_driver);
+}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.h b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.h
new file mode 100644
index 0000000..5b800f1
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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 __TILCDC_TFP410_H__
+#define __TILCDC_TFP410_H__
+
+/* sub-module for tfp410 dvi adaptor */
+
+int tilcdc_tfp410_init(void);
+void tilcdc_tfp410_fini(void);
+
+#endif /* __TILCDC_TFP410_H__ */
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 4cc2f05..0d55dbd 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -44,6 +44,7 @@
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/err.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_OMAP1_REV_2		0x20
@@ -1083,6 +1084,7 @@ omap_i2c_probe(struct platform_device *pdev)
 	int r;
 	u32 rev;
 	u16 minor, major, scheme;
+	struct pinctrl *pinctrl;
 
 	/* NOTE: driver uses the static register mapping */
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1252,6 +1254,13 @@ omap_i2c_probe(struct platform_device *pdev)
 
 	of_i2c_register_devices(adap);
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(dev->dev, "unable to select pin group\n");
+
+	/* 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); */
+
 	pm_runtime_mark_last_busy(dev->dev);
 	pm_runtime_put_autosuspend(dev->dev);
 
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 8e43872..25aa010 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -41,9 +41,12 @@
 #include <linux/device.h>
 #include <linux/i2c.h>
 #include <linux/i2c-mux.h>
+#include <linux/of.h>
+#include <linux/of_i2c.h>
 
 #include <linux/i2c/pca954x.h>
 
+
 #define PCA954X_MAX_NCHANS 8
 
 enum pca_type {
@@ -62,6 +65,10 @@ struct pca954x {
 	struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS];
 
 	u8 last_chan;		/* last register value */
+#ifdef CONFIG_OF
+	struct pca954x_platform_data of_pdata;
+	struct pca954x_platform_mode of_modes[8];	/* maximum is 8 */
+#endif
 };
 
 struct chip_desc {
@@ -117,6 +124,89 @@ static const struct i2c_device_id pca954x_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, pca954x_id);
 
+/* cast the type enum to a ptr */
+#define PCA_TYPE_2_PTR(x)	((const void *)(unsigned long)(x))
+/* cast the ptr back to an enum */
+#define PCA_PTR_2_TYPE(x)	((enum pca_type)(unsigned long)(x))
+
+static const struct of_device_id pca954x_of_match[] = {
+	{ .compatible = "nxp,pca9540", PCA_TYPE_2_PTR(pca_9540), },
+	{ .compatible = "nxp,pca9542", PCA_TYPE_2_PTR(pca_9542), },
+	{ .compatible = "nxp,pca9543", PCA_TYPE_2_PTR(pca_9543), },
+	{ .compatible = "nxp,pca9544", PCA_TYPE_2_PTR(pca_9544), },
+	{ .compatible = "nxp,pca9545", PCA_TYPE_2_PTR(pca_9545), },
+	{ .compatible = "nxp,pca9546", PCA_TYPE_2_PTR(pca_9546), },
+	{ .compatible = "nxp,pca9547", PCA_TYPE_2_PTR(pca_9547), },
+	{ .compatible = "nxp,pca9548", PCA_TYPE_2_PTR(pca_9548), },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, pca954x_of_match);
+
+#ifdef CONFIG_OF
+static int pca954x_get_ofdata(struct i2c_client *client,
+		struct pca954x_platform_data *pdata, struct pca954x *data)
+{
+	struct device_node *node = client->dev.of_node;
+	const struct of_device_id *id_match;
+	struct device_node *anode;
+	int num, busses_no, busses_max, ret;
+	u32 val;
+
+	if (!node)
+		return -ENODEV;
+
+	/* match the compatible device */
+	id_match = of_match_node(pca954x_of_match, node);
+	if (id_match == NULL) {
+		dev_err(&client->dev, "No pca954x compatible node!\n");
+		return -ENODEV;
+	}
+	data->type = PCA_PTR_2_TYPE(id_match->data);
+	busses_max = chips[data->type].nchans;
+
+	/* for each child node which is compatible to us */
+	busses_no = 0;
+	for_each_available_child_of_node(node, anode) {
+		if (!of_device_is_compatible(anode, "nxp,pca954x-bus"))
+			continue;
+		ret = of_property_read_u32(anode, "reg", &val);
+		if (ret != 0)
+			continue;
+		busses_no++;
+	}
+
+	if (busses_no == 0) {
+		dev_err(&client->dev, "No busses found!\n");
+		return -ENODEV;
+	}
+
+	/* ok, fill in everything now */
+	num = 0;
+	for_each_available_child_of_node(node, anode) {
+		if (!of_device_is_compatible(anode, "nxp,pca954x-bus"))
+			continue;
+		ret = of_property_read_u32(anode, "reg", &val);
+		if (ret != 0)
+			continue;
+		pdata->modes[num].adap_id = 0;	/* get adapter id */
+		pdata->modes[num].class = 0;	/* classs always 0 */
+		pdata->modes[num].deselect_on_exit =
+			of_property_read_bool(anode, "nxp,deselect-on-exit");
+		num++;
+	}
+	pdata->num_modes = num;
+
+	return 0;
+}
+#else
+static int pca954x_get_ofdata(struct i2c_client *client,
+		struct pca954x_platform_data *pdata, struct pca954x *data)
+{
+	return -ENODEV;	/* no of data (should never be called) */
+}
+#endif /* CONFIG_OF */
+
+
 /* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer()
    for this as they will try to lock adapter a second time */
 static int pca954x_reg_write(struct i2c_adapter *adap,
@@ -210,7 +300,20 @@ static int pca954x_probe(struct i2c_client *client,
 		goto exit_free;
 	}
 
-	data->type = id->driver_data;
+	/* platform device case; substitute platform data */
+	if (pdata == NULL) {
+		/* point to the filled in pdata */
+		pdata = &data->of_pdata;
+		pdata->modes = data->of_modes;
+		ret = pca954x_get_ofdata(client, pdata, data);
+		if (ret != 0) {
+			dev_err(&client->dev,
+				"Failed to get OF data\n");
+			goto exit_free;
+		}
+	} else
+		data->type = id->driver_data;
+
 	data->last_chan = 0;		   /* force the first selection */
 
 	/* Now create an adapter for each channel */
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 05e996f..bb59496 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -14,4 +14,42 @@ config HID_SENSOR_ACCEL_3D
 	  Say yes here to build support for the HID SENSOR
 	  accelerometers 3D.
 
+config KXSD9
+	tristate "Kionix KXSD9 Accelerometer Driver"
+	depends on SPI
+	help
+	  Say yes here to build support for the Kionix KXSD9 accelerometer.
+	  Currently this only supports the device via an SPI interface.
+
+config IIO_ST_ACCEL_3AXIS
+	tristate "STMicroelectronics accelerometers 3-Axis Driver"
+	depends on (I2C || SPI_MASTER) && SYSFS
+	select IIO_ST_SENSORS_CORE
+	select IIO_ST_ACCEL_I2C_3AXIS if (I2C)
+	select IIO_ST_ACCEL_SPI_3AXIS if (SPI_MASTER)
+	select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
+	select IIO_ST_ACCEL_BUFFER if (IIO_TRIGGERED_BUFFER)
+	help
+	  Say yes here to build support for STMicroelectronics accelerometers:
+	  LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
+	  LIS331DLH, LSM303DL, LSM303DLM, LSM330.
+
+	  This driver can also be built as a module. If so, will be created
+	  these modules:
+	  - st_accel (core functions for the driver [it is mandatory]);
+	  - st_accel_i2c (necessary for the I2C devices [optional*]);
+	  - st_accel_spi (necessary for the SPI devices [optional*]);
+
+	  (*) one of these is necessary to do something.
+
+config IIO_ST_ACCEL_I2C_3AXIS
+	tristate
+	depends on IIO_ST_ACCEL_3AXIS
+	depends on IIO_ST_SENSORS_I2C
+
+config IIO_ST_ACCEL_SPI_3AXIS
+	tristate
+	depends on IIO_ST_ACCEL_3AXIS
+	depends on IIO_ST_SENSORS_SPI
+
 endmenu
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 5bc6855..87d8fa2 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -3,3 +3,12 @@
 #
 
 obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
+
+obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o
+st_accel-y := st_accel_core.o
+st_accel-$(CONFIG_IIO_BUFFER) += st_accel_buffer.o
+
+obj-$(CONFIG_IIO_ST_ACCEL_I2C_3AXIS) += st_accel_i2c.o
+obj-$(CONFIG_IIO_ST_ACCEL_SPI_3AXIS) += st_accel_spi.o
+
+obj-$(CONFIG_KXSD9)	+= kxsd9.o
diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h
new file mode 100644
index 0000000..37949b9
--- /dev/null
+++ b/drivers/iio/accel/st_accel.h
@@ -0,0 +1,47 @@
+/*
+ * STMicroelectronics accelerometers driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ * v. 1.0.0
+ * Licensed under the GPL-2.
+ */
+
+#ifndef ST_ACCEL_H
+#define ST_ACCEL_H
+
+#include <linux/types.h>
+#include <linux/iio/common/st_sensors.h>
+
+#define LSM303DLHC_ACCEL_DEV_NAME	"lsm303dlhc_accel"
+#define LIS3DH_ACCEL_DEV_NAME		"lis3dh"
+#define LSM330D_ACCEL_DEV_NAME		"lsm330d_accel"
+#define LSM330DL_ACCEL_DEV_NAME		"lsm330dl_accel"
+#define LSM330DLC_ACCEL_DEV_NAME	"lsm330dlc_accel"
+#define LIS331DLH_ACCEL_DEV_NAME	"lis331dlh"
+#define LSM303DL_ACCEL_DEV_NAME		"lsm303dl_accel"
+#define LSM303DLH_ACCEL_DEV_NAME	"lsm303dlh_accel"
+#define LSM303DLM_ACCEL_DEV_NAME	"lsm303dlm_accel"
+#define LSM330_ACCEL_DEV_NAME		"lsm330_accel"
+
+int st_accel_common_probe(struct iio_dev *indio_dev);
+void st_accel_common_remove(struct iio_dev *indio_dev);
+
+#ifdef CONFIG_IIO_BUFFER
+int st_accel_allocate_ring(struct iio_dev *indio_dev);
+void st_accel_deallocate_ring(struct iio_dev *indio_dev);
+int st_accel_trig_set_state(struct iio_trigger *trig, bool state);
+#define ST_ACCEL_TRIGGER_SET_STATE (&st_accel_trig_set_state)
+#else /* CONFIG_IIO_BUFFER */
+static inline int st_accel_allocate_ring(struct iio_dev *indio_dev)
+{
+	return 0;
+}
+static inline void st_accel_deallocate_ring(struct iio_dev *indio_dev)
+{
+}
+#define ST_ACCEL_TRIGGER_SET_STATE NULL
+#endif /* CONFIG_IIO_BUFFER */
+
+#endif /* ST_ACCEL_H */
diff --git a/drivers/iio/accel/st_accel_buffer.c b/drivers/iio/accel/st_accel_buffer.c
new file mode 100644
index 0000000..6bd82c7
--- /dev/null
+++ b/drivers/iio/accel/st_accel_buffer.c
@@ -0,0 +1,114 @@
+/*
+ * STMicroelectronics accelerometers driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/delay.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/common/st_sensors.h>
+#include "st_accel.h"
+
+int st_accel_trig_set_state(struct iio_trigger *trig, bool state)
+{
+	struct iio_dev *indio_dev = trig->private_data;
+
+	return st_sensors_set_dataready_irq(indio_dev, state);
+}
+
+static int st_accel_buffer_preenable(struct iio_dev *indio_dev)
+{
+	int err;
+
+	err = st_sensors_set_enable(indio_dev, true);
+	if (err < 0)
+		goto st_accel_set_enable_error;
+
+	err = iio_sw_buffer_preenable(indio_dev);
+
+st_accel_set_enable_error:
+	return err;
+}
+
+static int st_accel_buffer_postenable(struct iio_dev *indio_dev)
+{
+	int err;
+	struct st_sensor_data *adata = iio_priv(indio_dev);
+
+	adata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (adata->buffer_data == NULL) {
+		err = -ENOMEM;
+		goto allocate_memory_error;
+	}
+
+	err = st_sensors_set_axis_enable(indio_dev,
+					(u8)indio_dev->active_scan_mask[0]);
+	if (err < 0)
+		goto st_accel_buffer_postenable_error;
+
+	err = iio_triggered_buffer_postenable(indio_dev);
+	if (err < 0)
+		goto st_accel_buffer_postenable_error;
+
+	return err;
+
+st_accel_buffer_postenable_error:
+	kfree(adata->buffer_data);
+allocate_memory_error:
+	return err;
+}
+
+static int st_accel_buffer_predisable(struct iio_dev *indio_dev)
+{
+	int err;
+	struct st_sensor_data *adata = iio_priv(indio_dev);
+
+	err = iio_triggered_buffer_predisable(indio_dev);
+	if (err < 0)
+		goto st_accel_buffer_predisable_error;
+
+	err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
+	if (err < 0)
+		goto st_accel_buffer_predisable_error;
+
+	err = st_sensors_set_enable(indio_dev, false);
+
+st_accel_buffer_predisable_error:
+	kfree(adata->buffer_data);
+	return err;
+}
+
+static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = {
+	.preenable = &st_accel_buffer_preenable,
+	.postenable = &st_accel_buffer_postenable,
+	.predisable = &st_accel_buffer_predisable,
+};
+
+int st_accel_allocate_ring(struct iio_dev *indio_dev)
+{
+	return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+		&st_sensors_trigger_handler, &st_accel_buffer_setup_ops);
+}
+
+void st_accel_deallocate_ring(struct iio_dev *indio_dev)
+{
+	iio_triggered_buffer_cleanup(indio_dev);
+}
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics accelerometers buffer");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
new file mode 100644
index 0000000..a235de2
--- /dev/null
+++ b/drivers/iio/accel/st_accel_core.c
@@ -0,0 +1,495 @@
+/*
+ * STMicroelectronics accelerometers driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+
+#include <linux/iio/common/st_sensors.h>
+#include "st_accel.h"
+
+/* DEFAULT VALUE FOR SENSORS */
+#define ST_ACCEL_DEFAULT_OUT_X_L_ADDR		0x28
+#define ST_ACCEL_DEFAULT_OUT_Y_L_ADDR		0x2a
+#define ST_ACCEL_DEFAULT_OUT_Z_L_ADDR		0x2c
+
+/* FULLSCALE */
+#define ST_ACCEL_FS_AVL_2G			2
+#define ST_ACCEL_FS_AVL_4G			4
+#define ST_ACCEL_FS_AVL_6G			6
+#define ST_ACCEL_FS_AVL_8G			8
+#define ST_ACCEL_FS_AVL_16G			16
+
+/* CUSTOM VALUES FOR SENSOR 1 */
+#define ST_ACCEL_1_WAI_EXP			0x33
+#define ST_ACCEL_1_ODR_ADDR			0x20
+#define ST_ACCEL_1_ODR_MASK			0xf0
+#define ST_ACCEL_1_ODR_AVL_1HZ_VAL		0x01
+#define ST_ACCEL_1_ODR_AVL_10HZ_VAL		0x02
+#define ST_ACCEL_1_ODR_AVL_25HZ_VAL		0x03
+#define ST_ACCEL_1_ODR_AVL_50HZ_VAL		0x04
+#define ST_ACCEL_1_ODR_AVL_100HZ_VAL		0x05
+#define ST_ACCEL_1_ODR_AVL_200HZ_VAL		0x06
+#define ST_ACCEL_1_ODR_AVL_400HZ_VAL		0x07
+#define ST_ACCEL_1_ODR_AVL_1600HZ_VAL		0x08
+#define ST_ACCEL_1_FS_ADDR			0x23
+#define ST_ACCEL_1_FS_MASK			0x30
+#define ST_ACCEL_1_FS_AVL_2_VAL			0x00
+#define ST_ACCEL_1_FS_AVL_4_VAL			0x01
+#define ST_ACCEL_1_FS_AVL_8_VAL			0x02
+#define ST_ACCEL_1_FS_AVL_16_VAL		0x03
+#define ST_ACCEL_1_FS_AVL_2_GAIN		IIO_G_TO_M_S_2(1000)
+#define ST_ACCEL_1_FS_AVL_4_GAIN		IIO_G_TO_M_S_2(2000)
+#define ST_ACCEL_1_FS_AVL_8_GAIN		IIO_G_TO_M_S_2(4000)
+#define ST_ACCEL_1_FS_AVL_16_GAIN		IIO_G_TO_M_S_2(12000)
+#define ST_ACCEL_1_BDU_ADDR			0x23
+#define ST_ACCEL_1_BDU_MASK			0x80
+#define ST_ACCEL_1_DRDY_IRQ_ADDR		0x22
+#define ST_ACCEL_1_DRDY_IRQ_MASK		0x10
+#define ST_ACCEL_1_MULTIREAD_BIT		true
+
+/* CUSTOM VALUES FOR SENSOR 2 */
+#define ST_ACCEL_2_WAI_EXP			0x32
+#define ST_ACCEL_2_ODR_ADDR			0x20
+#define ST_ACCEL_2_ODR_MASK			0x18
+#define ST_ACCEL_2_ODR_AVL_50HZ_VAL		0x00
+#define ST_ACCEL_2_ODR_AVL_100HZ_VAL		0x01
+#define ST_ACCEL_2_ODR_AVL_400HZ_VAL		0x02
+#define ST_ACCEL_2_ODR_AVL_1000HZ_VAL		0x03
+#define ST_ACCEL_2_PW_ADDR			0x20
+#define ST_ACCEL_2_PW_MASK			0xe0
+#define ST_ACCEL_2_FS_ADDR			0x23
+#define ST_ACCEL_2_FS_MASK			0x30
+#define ST_ACCEL_2_FS_AVL_2_VAL			0X00
+#define ST_ACCEL_2_FS_AVL_4_VAL			0X01
+#define ST_ACCEL_2_FS_AVL_8_VAL			0x03
+#define ST_ACCEL_2_FS_AVL_2_GAIN		IIO_G_TO_M_S_2(1000)
+#define ST_ACCEL_2_FS_AVL_4_GAIN		IIO_G_TO_M_S_2(2000)
+#define ST_ACCEL_2_FS_AVL_8_GAIN		IIO_G_TO_M_S_2(3900)
+#define ST_ACCEL_2_BDU_ADDR			0x23
+#define ST_ACCEL_2_BDU_MASK			0x80
+#define ST_ACCEL_2_DRDY_IRQ_ADDR		0x22
+#define ST_ACCEL_2_DRDY_IRQ_MASK		0x02
+#define ST_ACCEL_2_MULTIREAD_BIT		true
+
+/* CUSTOM VALUES FOR SENSOR 3 */
+#define ST_ACCEL_3_WAI_EXP			0x40
+#define ST_ACCEL_3_ODR_ADDR			0x20
+#define ST_ACCEL_3_ODR_MASK			0xf0
+#define ST_ACCEL_3_ODR_AVL_3HZ_VAL		0x01
+#define ST_ACCEL_3_ODR_AVL_6HZ_VAL		0x02
+#define ST_ACCEL_3_ODR_AVL_12HZ_VAL		0x03
+#define ST_ACCEL_3_ODR_AVL_25HZ_VAL		0x04
+#define ST_ACCEL_3_ODR_AVL_50HZ_VAL		0x05
+#define ST_ACCEL_3_ODR_AVL_100HZ_VAL		0x06
+#define ST_ACCEL_3_ODR_AVL_200HZ_VAL		0x07
+#define ST_ACCEL_3_ODR_AVL_400HZ_VAL		0x08
+#define ST_ACCEL_3_ODR_AVL_800HZ_VAL		0x09
+#define ST_ACCEL_3_ODR_AVL_1600HZ_VAL		0x0a
+#define ST_ACCEL_3_FS_ADDR			0x24
+#define ST_ACCEL_3_FS_MASK			0x38
+#define ST_ACCEL_3_FS_AVL_2_VAL			0X00
+#define ST_ACCEL_3_FS_AVL_4_VAL			0X01
+#define ST_ACCEL_3_FS_AVL_6_VAL			0x02
+#define ST_ACCEL_3_FS_AVL_8_VAL			0x03
+#define ST_ACCEL_3_FS_AVL_16_VAL		0x04
+#define ST_ACCEL_3_FS_AVL_2_GAIN		IIO_G_TO_M_S_2(61)
+#define ST_ACCEL_3_FS_AVL_4_GAIN		IIO_G_TO_M_S_2(122)
+#define ST_ACCEL_3_FS_AVL_6_GAIN		IIO_G_TO_M_S_2(183)
+#define ST_ACCEL_3_FS_AVL_8_GAIN		IIO_G_TO_M_S_2(244)
+#define ST_ACCEL_3_FS_AVL_16_GAIN		IIO_G_TO_M_S_2(732)
+#define ST_ACCEL_3_BDU_ADDR			0x20
+#define ST_ACCEL_3_BDU_MASK			0x08
+#define ST_ACCEL_3_DRDY_IRQ_ADDR		0x23
+#define ST_ACCEL_3_DRDY_IRQ_MASK		0x80
+#define ST_ACCEL_3_IG1_EN_ADDR			0x23
+#define ST_ACCEL_3_IG1_EN_MASK			0x08
+#define ST_ACCEL_3_MULTIREAD_BIT		false
+
+static const struct iio_chan_spec st_accel_12bit_channels[] = {
+	ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_X, IIO_MOD_X, IIO_LE,
+		ST_SENSORS_DEFAULT_12_REALBITS, ST_ACCEL_DEFAULT_OUT_X_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_Y, IIO_MOD_Y, IIO_LE,
+		ST_SENSORS_DEFAULT_12_REALBITS, ST_ACCEL_DEFAULT_OUT_Y_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_Z, IIO_MOD_Z, IIO_LE,
+		ST_SENSORS_DEFAULT_12_REALBITS, ST_ACCEL_DEFAULT_OUT_Z_L_ADDR),
+	IIO_CHAN_SOFT_TIMESTAMP(3)
+};
+
+static const struct iio_chan_spec st_accel_16bit_channels[] = {
+	ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_X, IIO_MOD_X, IIO_LE,
+		ST_SENSORS_DEFAULT_16_REALBITS, ST_ACCEL_DEFAULT_OUT_X_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_Y, IIO_MOD_Y, IIO_LE,
+		ST_SENSORS_DEFAULT_16_REALBITS, ST_ACCEL_DEFAULT_OUT_Y_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, ST_SENSORS_SCAN_Z, IIO_MOD_Z, IIO_LE,
+		ST_SENSORS_DEFAULT_16_REALBITS, ST_ACCEL_DEFAULT_OUT_Z_L_ADDR),
+	IIO_CHAN_SOFT_TIMESTAMP(3)
+};
+
+static const struct st_sensors st_accel_sensors[] = {
+	{
+		.wai = ST_ACCEL_1_WAI_EXP,
+		.sensors_supported = {
+			[0] = LIS3DH_ACCEL_DEV_NAME,
+			[1] = LSM303DLHC_ACCEL_DEV_NAME,
+			[2] = LSM330D_ACCEL_DEV_NAME,
+			[3] = LSM330DL_ACCEL_DEV_NAME,
+			[4] = LSM330DLC_ACCEL_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
+		.odr = {
+			.addr = ST_ACCEL_1_ODR_ADDR,
+			.mask = ST_ACCEL_1_ODR_MASK,
+			.odr_avl = {
+				{ 1, ST_ACCEL_1_ODR_AVL_1HZ_VAL, },
+				{ 10, ST_ACCEL_1_ODR_AVL_10HZ_VAL, },
+				{ 25, ST_ACCEL_1_ODR_AVL_25HZ_VAL, },
+				{ 50, ST_ACCEL_1_ODR_AVL_50HZ_VAL, },
+				{ 100, ST_ACCEL_1_ODR_AVL_100HZ_VAL, },
+				{ 200, ST_ACCEL_1_ODR_AVL_200HZ_VAL, },
+				{ 400, ST_ACCEL_1_ODR_AVL_400HZ_VAL, },
+				{ 1600, ST_ACCEL_1_ODR_AVL_1600HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_ACCEL_1_ODR_ADDR,
+			.mask = ST_ACCEL_1_ODR_MASK,
+			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+		},
+		.enable_axis = {
+			.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+		},
+		.fs = {
+			.addr = ST_ACCEL_1_FS_ADDR,
+			.mask = ST_ACCEL_1_FS_MASK,
+			.fs_avl = {
+				[0] = {
+					.num = ST_ACCEL_FS_AVL_2G,
+					.value = ST_ACCEL_1_FS_AVL_2_VAL,
+					.gain = ST_ACCEL_1_FS_AVL_2_GAIN,
+				},
+				[1] = {
+					.num = ST_ACCEL_FS_AVL_4G,
+					.value = ST_ACCEL_1_FS_AVL_4_VAL,
+					.gain = ST_ACCEL_1_FS_AVL_4_GAIN,
+				},
+				[2] = {
+					.num = ST_ACCEL_FS_AVL_8G,
+					.value = ST_ACCEL_1_FS_AVL_8_VAL,
+					.gain = ST_ACCEL_1_FS_AVL_8_GAIN,
+				},
+				[3] = {
+					.num = ST_ACCEL_FS_AVL_16G,
+					.value = ST_ACCEL_1_FS_AVL_16_VAL,
+					.gain = ST_ACCEL_1_FS_AVL_16_GAIN,
+				},
+			},
+		},
+		.bdu = {
+			.addr = ST_ACCEL_1_BDU_ADDR,
+			.mask = ST_ACCEL_1_BDU_MASK,
+		},
+		.drdy_irq = {
+			.addr = ST_ACCEL_1_DRDY_IRQ_ADDR,
+			.mask = ST_ACCEL_1_DRDY_IRQ_MASK,
+		},
+		.multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT,
+		.bootime = 2,
+	},
+	{
+		.wai = ST_ACCEL_2_WAI_EXP,
+		.sensors_supported = {
+			[0] = LIS331DLH_ACCEL_DEV_NAME,
+			[1] = LSM303DL_ACCEL_DEV_NAME,
+			[2] = LSM303DLH_ACCEL_DEV_NAME,
+			[3] = LSM303DLM_ACCEL_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
+		.odr = {
+			.addr = ST_ACCEL_2_ODR_ADDR,
+			.mask = ST_ACCEL_2_ODR_MASK,
+			.odr_avl = {
+				{ 50, ST_ACCEL_2_ODR_AVL_50HZ_VAL, },
+				{ 100, ST_ACCEL_2_ODR_AVL_100HZ_VAL, },
+				{ 400, ST_ACCEL_2_ODR_AVL_400HZ_VAL, },
+				{ 1000, ST_ACCEL_2_ODR_AVL_1000HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_ACCEL_2_PW_ADDR,
+			.mask = ST_ACCEL_2_PW_MASK,
+			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
+			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+		},
+		.enable_axis = {
+			.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+		},
+		.fs = {
+			.addr = ST_ACCEL_2_FS_ADDR,
+			.mask = ST_ACCEL_2_FS_MASK,
+			.fs_avl = {
+				[0] = {
+					.num = ST_ACCEL_FS_AVL_2G,
+					.value = ST_ACCEL_2_FS_AVL_2_VAL,
+					.gain = ST_ACCEL_2_FS_AVL_2_GAIN,
+				},
+				[1] = {
+					.num = ST_ACCEL_FS_AVL_4G,
+					.value = ST_ACCEL_2_FS_AVL_4_VAL,
+					.gain = ST_ACCEL_2_FS_AVL_4_GAIN,
+				},
+				[2] = {
+					.num = ST_ACCEL_FS_AVL_8G,
+					.value = ST_ACCEL_2_FS_AVL_8_VAL,
+					.gain = ST_ACCEL_2_FS_AVL_8_GAIN,
+				},
+			},
+		},
+		.bdu = {
+			.addr = ST_ACCEL_2_BDU_ADDR,
+			.mask = ST_ACCEL_2_BDU_MASK,
+		},
+		.drdy_irq = {
+			.addr = ST_ACCEL_2_DRDY_IRQ_ADDR,
+			.mask = ST_ACCEL_2_DRDY_IRQ_MASK,
+		},
+		.multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT,
+		.bootime = 2,
+	},
+	{
+		.wai = ST_ACCEL_3_WAI_EXP,
+		.sensors_supported = {
+			[0] = LSM330_ACCEL_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_accel_16bit_channels,
+		.odr = {
+			.addr = ST_ACCEL_3_ODR_ADDR,
+			.mask = ST_ACCEL_3_ODR_MASK,
+			.odr_avl = {
+				{ 3, ST_ACCEL_3_ODR_AVL_3HZ_VAL },
+				{ 6, ST_ACCEL_3_ODR_AVL_6HZ_VAL, },
+				{ 12, ST_ACCEL_3_ODR_AVL_12HZ_VAL, },
+				{ 25, ST_ACCEL_3_ODR_AVL_25HZ_VAL, },
+				{ 50, ST_ACCEL_3_ODR_AVL_50HZ_VAL, },
+				{ 100, ST_ACCEL_3_ODR_AVL_100HZ_VAL, },
+				{ 200, ST_ACCEL_3_ODR_AVL_200HZ_VAL, },
+				{ 400, ST_ACCEL_3_ODR_AVL_400HZ_VAL, },
+				{ 800, ST_ACCEL_3_ODR_AVL_800HZ_VAL, },
+				{ 1600, ST_ACCEL_3_ODR_AVL_1600HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_ACCEL_3_ODR_ADDR,
+			.mask = ST_ACCEL_3_ODR_MASK,
+			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+		},
+		.enable_axis = {
+			.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+		},
+		.fs = {
+			.addr = ST_ACCEL_3_FS_ADDR,
+			.mask = ST_ACCEL_3_FS_MASK,
+			.fs_avl = {
+				[0] = {
+					.num = ST_ACCEL_FS_AVL_2G,
+					.value = ST_ACCEL_3_FS_AVL_2_VAL,
+					.gain = ST_ACCEL_3_FS_AVL_2_GAIN,
+				},
+				[1] = {
+					.num = ST_ACCEL_FS_AVL_4G,
+					.value = ST_ACCEL_3_FS_AVL_4_VAL,
+					.gain = ST_ACCEL_3_FS_AVL_4_GAIN,
+				},
+				[2] = {
+					.num = ST_ACCEL_FS_AVL_6G,
+					.value = ST_ACCEL_3_FS_AVL_6_VAL,
+					.gain = ST_ACCEL_3_FS_AVL_6_GAIN,
+				},
+				[3] = {
+					.num = ST_ACCEL_FS_AVL_8G,
+					.value = ST_ACCEL_3_FS_AVL_8_VAL,
+					.gain = ST_ACCEL_3_FS_AVL_8_GAIN,
+				},
+				[4] = {
+					.num = ST_ACCEL_FS_AVL_16G,
+					.value = ST_ACCEL_3_FS_AVL_16_VAL,
+					.gain = ST_ACCEL_3_FS_AVL_16_GAIN,
+				},
+			},
+		},
+		.bdu = {
+			.addr = ST_ACCEL_3_BDU_ADDR,
+			.mask = ST_ACCEL_3_BDU_MASK,
+		},
+		.drdy_irq = {
+			.addr = ST_ACCEL_3_DRDY_IRQ_ADDR,
+			.mask = ST_ACCEL_3_DRDY_IRQ_MASK,
+			.ig1 = {
+				.en_addr = ST_ACCEL_3_IG1_EN_ADDR,
+				.en_mask = ST_ACCEL_3_IG1_EN_MASK,
+			},
+		},
+		.multi_read_bit = ST_ACCEL_3_MULTIREAD_BIT,
+		.bootime = 2,
+	},
+};
+
+static int st_accel_read_raw(struct iio_dev *indio_dev,
+			struct iio_chan_spec const *ch, int *val,
+							int *val2, long mask)
+{
+	int err;
+	struct st_sensor_data *adata = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		err = st_sensors_read_info_raw(indio_dev, ch, val);
+		if (err < 0)
+			goto read_error;
+
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = adata->current_fullscale->gain;
+		return IIO_VAL_INT_PLUS_MICRO;
+	default:
+		return -EINVAL;
+	}
+
+read_error:
+	return err;
+}
+
+static int st_accel_write_raw(struct iio_dev *indio_dev,
+		struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+	int err;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return err;
+}
+
+static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
+static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
+static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_accel_scale_available);
+
+static struct attribute *st_accel_attributes[] = {
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+	&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
+	&iio_dev_attr_sampling_frequency.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group st_accel_attribute_group = {
+	.attrs = st_accel_attributes,
+};
+
+static const struct iio_info accel_info = {
+	.driver_module = THIS_MODULE,
+	.attrs = &st_accel_attribute_group,
+	.read_raw = &st_accel_read_raw,
+	.write_raw = &st_accel_write_raw,
+};
+
+static const struct iio_trigger_ops st_accel_trigger_ops = {
+	.owner = THIS_MODULE,
+	.set_trigger_state = ST_ACCEL_TRIGGER_SET_STATE,
+};
+
+int st_accel_common_probe(struct iio_dev *indio_dev)
+{
+	int err;
+	struct st_sensor_data *adata = iio_priv(indio_dev);
+
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->info = &accel_info;
+
+	err = st_sensors_check_device_support(indio_dev,
+				ARRAY_SIZE(st_accel_sensors), st_accel_sensors);
+	if (err < 0)
+		goto st_accel_common_probe_error;
+
+	adata->multiread_bit = adata->sensor->multi_read_bit;
+	indio_dev->channels = adata->sensor->ch;
+	indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
+
+	adata->current_fullscale = (struct st_sensor_fullscale_avl *)
+						&adata->sensor->fs.fs_avl[0];
+	adata->odr = adata->sensor->odr.odr_avl[0].hz;
+
+	err = st_sensors_init_sensor(indio_dev);
+	if (err < 0)
+		goto st_accel_common_probe_error;
+
+	if (adata->get_irq_data_ready(indio_dev) > 0) {
+		err = st_accel_allocate_ring(indio_dev);
+		if (err < 0)
+			goto st_accel_common_probe_error;
+
+		err = st_sensors_allocate_trigger(indio_dev,
+							&st_accel_trigger_ops);
+		if (err < 0)
+			goto st_accel_probe_trigger_error;
+	}
+
+	err = iio_device_register(indio_dev);
+	if (err)
+		goto st_accel_device_register_error;
+
+	return err;
+
+st_accel_device_register_error:
+	if (adata->get_irq_data_ready(indio_dev) > 0)
+		st_sensors_deallocate_trigger(indio_dev);
+st_accel_probe_trigger_error:
+	if (adata->get_irq_data_ready(indio_dev) > 0)
+		st_accel_deallocate_ring(indio_dev);
+st_accel_common_probe_error:
+	return err;
+}
+EXPORT_SYMBOL(st_accel_common_probe);
+
+void st_accel_common_remove(struct iio_dev *indio_dev)
+{
+	struct st_sensor_data *adata = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	if (adata->get_irq_data_ready(indio_dev) > 0) {
+		st_sensors_deallocate_trigger(indio_dev);
+		st_accel_deallocate_ring(indio_dev);
+	}
+	iio_device_free(indio_dev);
+}
+EXPORT_SYMBOL(st_accel_common_remove);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics accelerometers driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
new file mode 100644
index 0000000..90b8ddf
--- /dev/null
+++ b/drivers/iio/accel/st_accel_i2c.c
@@ -0,0 +1,87 @@
+/*
+ * STMicroelectronics accelerometers driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+
+#include <linux/iio/common/st_sensors.h>
+#include <linux/iio/common/st_sensors_i2c.h>
+#include "st_accel.h"
+
+static int st_accel_i2c_probe(struct i2c_client *client,
+						const struct i2c_device_id *id)
+{
+	struct iio_dev *indio_dev;
+	struct st_sensor_data *adata;
+	int err;
+
+	indio_dev = iio_device_alloc(sizeof(*adata));
+	if (indio_dev == NULL) {
+		err = -ENOMEM;
+		goto iio_device_alloc_error;
+	}
+
+	adata = iio_priv(indio_dev);
+	adata->dev = &client->dev;
+
+	st_sensors_i2c_configure(indio_dev, client, adata);
+
+	err = st_accel_common_probe(indio_dev);
+	if (err < 0)
+		goto st_accel_common_probe_error;
+
+	return 0;
+
+st_accel_common_probe_error:
+	iio_device_free(indio_dev);
+iio_device_alloc_error:
+	return err;
+}
+
+static int st_accel_i2c_remove(struct i2c_client *client)
+{
+	st_accel_common_remove(i2c_get_clientdata(client));
+
+	return 0;
+}
+
+static const struct i2c_device_id st_accel_id_table[] = {
+	{ LSM303DLH_ACCEL_DEV_NAME },
+	{ LSM303DLHC_ACCEL_DEV_NAME },
+	{ LIS3DH_ACCEL_DEV_NAME },
+	{ LSM330D_ACCEL_DEV_NAME },
+	{ LSM330DL_ACCEL_DEV_NAME },
+	{ LSM330DLC_ACCEL_DEV_NAME },
+	{ LIS331DLH_ACCEL_DEV_NAME },
+	{ LSM303DL_ACCEL_DEV_NAME },
+	{ LSM303DLM_ACCEL_DEV_NAME },
+	{ LSM330_ACCEL_DEV_NAME },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
+
+static struct i2c_driver st_accel_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "st-accel-i2c",
+	},
+	.probe = st_accel_i2c_probe,
+	.remove = st_accel_i2c_remove,
+	.id_table = st_accel_id_table,
+};
+module_i2c_driver(st_accel_driver);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics accelerometers i2c driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c
new file mode 100644
index 0000000..dbd45c0
--- /dev/null
+++ b/drivers/iio/accel/st_accel_spi.c
@@ -0,0 +1,86 @@
+/*
+ * STMicroelectronics accelerometers driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+
+#include <linux/iio/common/st_sensors.h>
+#include <linux/iio/common/st_sensors_spi.h>
+#include "st_accel.h"
+
+static int st_accel_spi_probe(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev;
+	struct st_sensor_data *adata;
+	int err;
+
+	indio_dev = iio_device_alloc(sizeof(*adata));
+	if (indio_dev == NULL) {
+		err = -ENOMEM;
+		goto iio_device_alloc_error;
+	}
+
+	adata = iio_priv(indio_dev);
+	adata->dev = &spi->dev;
+
+	st_sensors_spi_configure(indio_dev, spi, adata);
+
+	err = st_accel_common_probe(indio_dev);
+	if (err < 0)
+		goto st_accel_common_probe_error;
+
+	return 0;
+
+st_accel_common_probe_error:
+	iio_device_free(indio_dev);
+iio_device_alloc_error:
+	return err;
+}
+
+static int st_accel_spi_remove(struct spi_device *spi)
+{
+	st_accel_common_remove(spi_get_drvdata(spi));
+
+	return 0;
+}
+
+static const struct spi_device_id st_accel_id_table[] = {
+	{ LSM303DLH_ACCEL_DEV_NAME },
+	{ LSM303DLHC_ACCEL_DEV_NAME },
+	{ LIS3DH_ACCEL_DEV_NAME },
+	{ LSM330D_ACCEL_DEV_NAME },
+	{ LSM330DL_ACCEL_DEV_NAME },
+	{ LSM330DLC_ACCEL_DEV_NAME },
+	{ LIS331DLH_ACCEL_DEV_NAME },
+	{ LSM303DL_ACCEL_DEV_NAME },
+	{ LSM303DLM_ACCEL_DEV_NAME },
+	{ LSM330_ACCEL_DEV_NAME },
+	{},
+};
+MODULE_DEVICE_TABLE(spi, st_accel_id_table);
+
+static struct spi_driver st_accel_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "st-accel-spi",
+	},
+	.probe = st_accel_spi_probe,
+	.remove = st_accel_spi_remove,
+	.id_table = st_accel_id_table,
+};
+module_spi_driver(st_accel_driver);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics accelerometers spi driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index cd030e1..c030078 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -22,6 +22,11 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/iio/iio.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+#include <linux/math64.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
 #include <linux/platform_data/ti_am335x_adc.h>
@@ -29,6 +34,8 @@
 struct tiadc_device {
 	struct ti_tscadc_dev *mfd_tscadc;
 	int channels;
+	u8 channel_line[8];
+	u8 channel_step[8];
 };
 
 static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
@@ -42,10 +49,19 @@ static void tiadc_writel(struct tiadc_device *adc, unsigned int reg,
 	writel(val, adc->mfd_tscadc->tscadc_base + reg);
 }
 
+static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
+{
+	u32 step_en;
+
+	step_en = ((1 << adc_dev->channels) - 1);
+	step_en <<= TOTAL_STEPS - adc_dev->channels + 1;
+	return step_en;
+}
+
 static void tiadc_step_config(struct tiadc_device *adc_dev)
 {
 	unsigned int stepconfig;
-	int i, channels = 0, steps;
+	int i, steps;
 
 	/*
 	 * There are 16 configurable steps and 8 analog input
@@ -58,43 +74,63 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 	 */
 
 	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),
+	for (i = 0; i < adc_dev->channels; i++) {
+		int chan;
+
+		chan = adc_dev->channel_line[i];
+		tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
+				stepconfig | STEPCONFIG_INP(chan));
+		tiadc_writel(adc_dev, REG_STEPDELAY(steps),
 				STEPCONFIG_OPENDLY);
-		channels++;
+		adc_dev->channel_step[i] = steps;
+		steps++;
 	}
-	tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
+
 }
 
+static const char * const chan_name_ain[] = {
+	"AIN0",
+	"AIN1",
+	"AIN2",
+	"AIN3",
+	"AIN4",
+	"AIN5",
+	"AIN6",
+	"AIN7",
+};
+
 static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
 {
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	struct iio_chan_spec *chan_array;
+	struct iio_chan_spec *chan;
 	int i;
 
 	indio_dev->num_channels = channels;
-	chan_array = kcalloc(indio_dev->num_channels,
+	chan_array = kcalloc(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 = chan_array;
+	for (i = 0; i < channels; i++, chan++) {
+
 		chan->type = IIO_VOLTAGE;
 		chan->indexed = 1;
-		chan->channel = i;
-		chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT;
+		chan->channel = adc_dev->channel_line[i];
+		chan->info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT 
+                                | IIO_CHAN_INFO_SCALE_SEPARATE_BIT;
+		chan->datasheet_name = chan_name_ain[chan->channel];
+		chan->scan_type.sign = 'u';
+		chan->scan_type.realbits = 12;
+		chan->scan_type.storagebits = 32;
 	}
 
 	indio_dev->channels = chan_array;
 
-	return indio_dev->num_channels;
+	return 0;
 }
 
 static void tiadc_channels_remove(struct iio_dev *indio_dev)
@@ -107,9 +143,22 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 		int *val, int *val2, long mask)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
-	int i;
-	unsigned int fifo1count, readx1;
-
+	int i, map_val;
+	unsigned int fifo1count, read, stepid;
+	u32 step = UINT_MAX;
+	bool found = false;
+	u32 step_en;
+	unsigned long timeout = jiffies + usecs_to_jiffies
+                       (IDLE_TIMEOUT * adc_dev->channels);
+	step_en = get_adc_step_mask(adc_dev);
+	am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
+
+	/* Wait for ADC sequencer to complete sampling */
+	while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) {
+		if (time_after(jiffies, timeout))
+			return -EAGAIN;
+       }
+	map_val = chan->channel + TOTAL_CHANNELS;
 	/*
 	 * When the sub-system is first enabled,
 	 * the sequencer will always start with the
@@ -121,14 +170,42 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 	 * Hence we need to flush out this data.
 	 */
 
+	for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
+		if (chan->channel == adc_dev->channel_line[i]) {
+			step = adc_dev->channel_step[i];
+			break;
+		}
+	}
+	if (WARN_ON_ONCE(step == UINT_MAX))
+		return -EINVAL;
+
 	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
 	for (i = 0; i < fifo1count; i++) {
-		readx1 = tiadc_readl(adc_dev, REG_FIFO1);
-		if (i == chan->channel)
-			*val = readx1 & 0xfff;
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+		stepid = read & FIFOREAD_CHNLID_MASK;
+		stepid = stepid >> 0x10;
+
+		if (stepid == map_val) {
+			read = read & FIFOREAD_DATA_MASK;
+			found = true;
+			*val = read;
+		}
 	}
-	tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
-
+        
+        switch (mask){
+            case IIO_CHAN_INFO_RAW : /*Do nothing. Above code works fine.*/
+                   break;        
+            case IIO_CHAN_INFO_SCALE : {
+                    /*12 Bit adc. Scale value for 1800mV AVDD. Ideally
+                    AVDD should come from DT.*/
+                    *val = div_u64( (u64)(*val) * 1800 , 4096);
+                    break;
+            }                
+            default: break; 
+        }   
+    
+	if (found == false)
+		return -EBUSY;
 	return IIO_VAL_INT;
 }
 
@@ -140,12 +217,16 @@ static int 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;
+	struct ti_tscadc_dev	*tscadc_dev = ti_tscadc_dev_get(pdev);
+	struct mfd_tscadc_board	*pdata = tscadc_dev->dev->platform_data;
+	struct device_node	*node = tscadc_dev->dev->of_node;
+	struct property		*prop;
+	const __be32		*cur;
 	int			err;
+	u32			val;
+	int			channels = 0;
 
-	pdata = tscadc_dev->dev->platform_data;
-	if (!pdata || !pdata->adc_init) {
+	if (!pdata && !node) {
 		dev_err(&pdev->dev, "Could not find platform data\n");
 		return -EINVAL;
 	}
@@ -158,8 +239,18 @@ static int tiadc_probe(struct platform_device *pdev)
 	}
 	adc_dev = iio_priv(indio_dev);
 
-	adc_dev->mfd_tscadc = tscadc_dev;
-	adc_dev->channels = pdata->adc_init->adc_channels;
+	adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev);
+
+	if (pdata)
+		adc_dev->channels = pdata->adc_init->adc_channels;
+	else {
+		node = of_get_child_by_name(node, "adc");
+		of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
+				adc_dev->channel_line[channels] = val;
+			channels++;
+		}
+		adc_dev->channels = channels;
+	}
 
 	indio_dev->dev.parent = &pdev->dev;
 	indio_dev->name = dev_name(&pdev->dev);
@@ -191,10 +282,15 @@ err_ret:
 static int tiadc_remove(struct platform_device *pdev)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	u32 step_en;
 
 	iio_device_unregister(indio_dev);
 	tiadc_channels_remove(indio_dev);
 
+	step_en = get_adc_step_mask(adc_dev);
+	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
+
 	iio_device_free(indio_dev);
 
 	return 0;
@@ -205,9 +301,10 @@ 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;
+	struct ti_tscadc_dev *tscadc_dev;
 	unsigned int idle;
 
+	tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
 	if (!device_may_wakeup(tscadc_dev->dev)) {
 		idle = tiadc_readl(adc_dev, REG_CTRL);
 		idle &= ~(CNTRLREG_TSCSSENB);
@@ -243,11 +340,18 @@ static const struct dev_pm_ops tiadc_pm_ops = {
 #define TIADC_PM_OPS NULL
 #endif
 
+static const struct of_device_id ti_adc_dt_ids[] = {
+	{ .compatible = "ti,ti-tscadc", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ti_adc_dt_ids);
+
 static struct platform_driver tiadc_driver = {
 	.driver = {
 		.name   = "tiadc",
 		.owner	= THIS_MODULE,
 		.pm	= TIADC_PM_OPS,
+		.of_match_table = of_match_ptr(ti_adc_dt_ids),
 	},
 	.probe	= tiadc_probe,
 	.remove	= tiadc_remove,
diff --git a/drivers/iio/common/Kconfig b/drivers/iio/common/Kconfig
index ed45ee5..0b6e97d 100644
--- a/drivers/iio/common/Kconfig
+++ b/drivers/iio/common/Kconfig
@@ -3,3 +3,4 @@
 #
 
 source "drivers/iio/common/hid-sensors/Kconfig"
+source "drivers/iio/common/st_sensors/Kconfig"
diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile
index 8158400..c2352be 100644
--- a/drivers/iio/common/Makefile
+++ b/drivers/iio/common/Makefile
@@ -7,3 +7,4 @@
 #
 
 obj-y += hid-sensors/
+obj-y += st_sensors/
diff --git a/drivers/iio/common/st_sensors/Kconfig b/drivers/iio/common/st_sensors/Kconfig
new file mode 100644
index 0000000..84b2dca
--- /dev/null
+++ b/drivers/iio/common/st_sensors/Kconfig
@@ -0,0 +1,14 @@
+#
+# Hid Sensor common modules
+#
+
+config IIO_ST_SENSORS_I2C
+	tristate
+
+config IIO_ST_SENSORS_SPI
+	tristate
+
+config IIO_ST_SENSORS_CORE
+	tristate
+	select IIO_ST_SENSORS_I2C if I2C
+	select IIO_ST_SENSORS_SPI if SPI_MASTER
diff --git a/drivers/iio/common/st_sensors/Makefile b/drivers/iio/common/st_sensors/Makefile
new file mode 100644
index 0000000..9f3e24f
--- /dev/null
+++ b/drivers/iio/common/st_sensors/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the STMicroelectronics sensor common modules.
+#
+
+obj-$(CONFIG_IIO_ST_SENSORS_I2C) += st_sensors_i2c.o
+obj-$(CONFIG_IIO_ST_SENSORS_SPI) += st_sensors_spi.o
+obj-$(CONFIG_IIO_ST_SENSORS_CORE) += st_sensors.o
+st_sensors-y := st_sensors_core.o
+st_sensors-$(CONFIG_IIO_BUFFER) += st_sensors_buffer.o
+st_sensors-$(CONFIG_IIO_TRIGGER) += st_sensors_trigger.o
diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c
new file mode 100644
index 0000000..09b236d
--- /dev/null
+++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c
@@ -0,0 +1,116 @@
+/*
+ * STMicroelectronics sensors buffer library driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+#include <linux/interrupt.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/irqreturn.h>
+
+#include <linux/iio/common/st_sensors.h>
+
+
+int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
+{
+	int i, n = 0, len;
+	u8 addr[ST_SENSORS_NUMBER_DATA_CHANNELS];
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	for (i = 0; i < ST_SENSORS_NUMBER_DATA_CHANNELS; i++) {
+		if (test_bit(i, indio_dev->active_scan_mask)) {
+			addr[n] = indio_dev->channels[i].address;
+			n++;
+		}
+	}
+	switch (n) {
+	case 1:
+		len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
+			addr[0], ST_SENSORS_BYTE_FOR_CHANNEL, buf,
+			sdata->multiread_bit);
+		break;
+	case 2:
+		if ((addr[1] - addr[0]) == ST_SENSORS_BYTE_FOR_CHANNEL) {
+			len = sdata->tf->read_multiple_byte(&sdata->tb,
+					sdata->dev, addr[0],
+					ST_SENSORS_BYTE_FOR_CHANNEL*n,
+					buf, sdata->multiread_bit);
+		} else {
+			u8 rx_array[ST_SENSORS_BYTE_FOR_CHANNEL*
+				    ST_SENSORS_NUMBER_DATA_CHANNELS];
+			len = sdata->tf->read_multiple_byte(&sdata->tb,
+				sdata->dev, addr[0],
+				ST_SENSORS_BYTE_FOR_CHANNEL*
+				ST_SENSORS_NUMBER_DATA_CHANNELS,
+				rx_array, sdata->multiread_bit);
+			if (len < 0)
+				goto read_data_channels_error;
+
+			for (i = 0; i < n * ST_SENSORS_NUMBER_DATA_CHANNELS;
+									i++) {
+				if (i < n)
+					buf[i] = rx_array[i];
+				else
+					buf[i] = rx_array[n + i];
+			}
+			len = ST_SENSORS_BYTE_FOR_CHANNEL*n;
+		}
+		break;
+	case 3:
+		len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
+			addr[0], ST_SENSORS_BYTE_FOR_CHANNEL*
+			ST_SENSORS_NUMBER_DATA_CHANNELS,
+			buf, sdata->multiread_bit);
+		break;
+	default:
+		len = -EINVAL;
+		goto read_data_channels_error;
+	}
+	if (len != ST_SENSORS_BYTE_FOR_CHANNEL*n) {
+		len = -EIO;
+		goto read_data_channels_error;
+	}
+
+read_data_channels_error:
+	return len;
+}
+EXPORT_SYMBOL(st_sensors_get_buffer_element);
+
+irqreturn_t st_sensors_trigger_handler(int irq, void *p)
+{
+	int len;
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	len = st_sensors_get_buffer_element(indio_dev, sdata->buffer_data);
+	if (len < 0)
+		goto st_sensors_get_buffer_element_error;
+
+	if (indio_dev->scan_timestamp)
+		*(s64 *)((u8 *)sdata->buffer_data +
+				ALIGN(len, sizeof(s64))) = pf->timestamp;
+
+	iio_push_to_buffers(indio_dev, sdata->buffer_data);
+
+st_sensors_get_buffer_element_error:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(st_sensors_trigger_handler);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics ST-sensors buffer");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
new file mode 100644
index 0000000..fba6d68
--- /dev/null
+++ b/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -0,0 +1,460 @@
+/*
+ * STMicroelectronics sensors core library driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <asm/unaligned.h>
+
+#include <linux/iio/common/st_sensors.h>
+
+
+#define ST_SENSORS_WAI_ADDRESS		0x0f
+
+static int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
+						u8 reg_addr, u8 mask, u8 data)
+{
+	int err;
+	u8 new_data;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	err = sdata->tf->read_byte(&sdata->tb, sdata->dev, reg_addr, &new_data);
+	if (err < 0)
+		goto st_sensors_write_data_with_mask_error;
+
+	new_data = ((new_data & (~mask)) | ((data << __ffs(mask)) & mask));
+	err = sdata->tf->write_byte(&sdata->tb, sdata->dev, reg_addr, new_data);
+
+st_sensors_write_data_with_mask_error:
+	return err;
+}
+
+int st_sensors_get_sampling_frequency_avl(struct iio_dev *indio_dev, char *buf)
+{
+	int i, len = 0;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	mutex_lock(&indio_dev->mlock);
+	for (i = 0; i < ST_SENSORS_ODR_LIST_MAX; i++) {
+		if (sdata->sensor->odr.odr_avl[i].hz == 0)
+			break;
+
+		len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
+					sdata->sensor->odr.odr_avl[i].hz);
+	}
+	mutex_unlock(&indio_dev->mlock);
+	buf[len - 1] = '\n';
+
+	return len;
+}
+EXPORT_SYMBOL(st_sensors_get_sampling_frequency_avl);
+
+int st_sensors_get_scale_avl(struct iio_dev *indio_dev, char *buf)
+{
+	int i, len = 0;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	mutex_lock(&indio_dev->mlock);
+	for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
+		if (sdata->sensor->fs.fs_avl[i].num == 0)
+			break;
+
+		len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ",
+					sdata->sensor->fs.fs_avl[i].gain);
+	}
+	mutex_unlock(&indio_dev->mlock);
+	buf[len - 1] = '\n';
+
+	return len;
+}
+EXPORT_SYMBOL(st_sensors_get_scale_avl);
+
+static int st_sensors_match_odr(struct st_sensors *sensor,
+			unsigned int odr, struct st_sensor_odr_avl *odr_out)
+{
+	int i, ret = -EINVAL;
+
+	for (i = 0; i < ST_SENSORS_ODR_LIST_MAX; i++) {
+		if (sensor->odr.odr_avl[i].hz == 0)
+			goto st_sensors_match_odr_error;
+
+		if (sensor->odr.odr_avl[i].hz == odr) {
+			odr_out->hz = sensor->odr.odr_avl[i].hz;
+			odr_out->value = sensor->odr.odr_avl[i].value;
+			ret = 0;
+			break;
+		}
+	}
+
+st_sensors_match_odr_error:
+	return ret;
+}
+
+int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr)
+{
+	int err;
+	struct st_sensor_odr_avl odr_out;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	err = st_sensors_match_odr(sdata->sensor, odr, &odr_out);
+	if (err < 0)
+		goto st_sensors_match_odr_error;
+
+	if ((sdata->sensor->odr.addr == sdata->sensor->pw.addr) &&
+			(sdata->sensor->odr.mask == sdata->sensor->pw.mask)) {
+		if (sdata->enabled == true) {
+			err = st_sensors_write_data_with_mask(indio_dev,
+				sdata->sensor->odr.addr,
+				sdata->sensor->odr.mask,
+				odr_out.value);
+		} else {
+			err = 0;
+		}
+	} else {
+		err = st_sensors_write_data_with_mask(indio_dev,
+			sdata->sensor->odr.addr, sdata->sensor->odr.mask,
+			odr_out.value);
+	}
+	if (err >= 0)
+		sdata->odr = odr_out.hz;
+
+st_sensors_match_odr_error:
+	return err;
+}
+EXPORT_SYMBOL(st_sensors_set_odr);
+
+static int st_sensors_match_fs(struct st_sensors *sensor,
+					unsigned int fs, int *index_fs_avl)
+{
+	int i, ret = -EINVAL;
+
+	for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
+		if (sensor->fs.fs_avl[i].num == 0)
+			goto st_sensors_match_odr_error;
+
+		if (sensor->fs.fs_avl[i].num == fs) {
+			*index_fs_avl = i;
+			ret = 0;
+			break;
+		}
+	}
+
+st_sensors_match_odr_error:
+	return ret;
+}
+
+static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
+{
+	int err, i;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	err = st_sensors_match_fs(sdata->sensor, fs, &i);
+	if (err < 0)
+		goto st_accel_set_fullscale_error;
+
+	err = st_sensors_write_data_with_mask(indio_dev,
+				sdata->sensor->fs.addr,
+				sdata->sensor->fs.mask,
+				sdata->sensor->fs.fs_avl[i].value);
+	if (err < 0)
+		goto st_accel_set_fullscale_error;
+
+	sdata->current_fullscale = (struct st_sensor_fullscale_avl *)
+						&sdata->sensor->fs.fs_avl[i];
+	return err;
+
+st_accel_set_fullscale_error:
+	dev_err(&indio_dev->dev, "failed to set new fullscale.\n");
+	return err;
+}
+
+int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable)
+{
+	bool found;
+	u8 tmp_value;
+	int err = -EINVAL;
+	struct st_sensor_odr_avl odr_out;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	if (enable) {
+		found = false;
+		tmp_value = sdata->sensor->pw.value_on;
+		if ((sdata->sensor->odr.addr == sdata->sensor->pw.addr) &&
+			(sdata->sensor->odr.mask == sdata->sensor->pw.mask)) {
+			err = st_sensors_match_odr(sdata->sensor,
+							sdata->odr, &odr_out);
+			if (err < 0)
+				goto set_enable_error;
+			tmp_value = odr_out.value;
+			found = true;
+		}
+		err = st_sensors_write_data_with_mask(indio_dev,
+				sdata->sensor->pw.addr,
+				sdata->sensor->pw.mask, tmp_value);
+		if (err < 0)
+			goto set_enable_error;
+
+		sdata->enabled = true;
+
+		if (found)
+			sdata->odr = odr_out.hz;
+	} else {
+		err = st_sensors_write_data_with_mask(indio_dev,
+				sdata->sensor->pw.addr,
+				sdata->sensor->pw.mask,
+				sdata->sensor->pw.value_off);
+		if (err < 0)
+			goto set_enable_error;
+
+		sdata->enabled = false;
+	}
+
+set_enable_error:
+	return err;
+}
+EXPORT_SYMBOL(st_sensors_set_enable);
+
+int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
+{
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	return st_sensors_write_data_with_mask(indio_dev,
+				sdata->sensor->enable_axis.addr,
+				sdata->sensor->enable_axis.mask, axis_enable);
+}
+EXPORT_SYMBOL(st_sensors_set_axis_enable);
+
+int st_sensors_init_sensor(struct iio_dev *indio_dev)
+{
+	int err;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	mutex_init(&sdata->tb.buf_lock);
+
+	err = st_sensors_set_enable(indio_dev, false);
+	if (err < 0)
+		goto init_error;
+
+	err = st_sensors_set_fullscale(indio_dev,
+						sdata->current_fullscale->num);
+	if (err < 0)
+		goto init_error;
+
+	err = st_sensors_set_odr(indio_dev, sdata->odr);
+	if (err < 0)
+		goto init_error;
+
+	/* set BDU */
+	err = st_sensors_write_data_with_mask(indio_dev,
+			sdata->sensor->bdu.addr, sdata->sensor->bdu.mask, true);
+	if (err < 0)
+		goto init_error;
+
+	err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
+
+init_error:
+	return err;
+}
+EXPORT_SYMBOL(st_sensors_init_sensor);
+
+int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
+{
+	int err;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	/* Enable/Disable the interrupt generator 1. */
+	if (sdata->sensor->drdy_irq.ig1.en_addr > 0) {
+		err = st_sensors_write_data_with_mask(indio_dev,
+			sdata->sensor->drdy_irq.ig1.en_addr,
+			sdata->sensor->drdy_irq.ig1.en_mask, (int)enable);
+		if (err < 0)
+			goto st_accel_set_dataready_irq_error;
+	}
+
+	/* Enable/Disable the interrupt generator for data ready. */
+	err = st_sensors_write_data_with_mask(indio_dev,
+			sdata->sensor->drdy_irq.addr,
+			sdata->sensor->drdy_irq.mask, (int)enable);
+
+st_accel_set_dataready_irq_error:
+	return err;
+}
+EXPORT_SYMBOL(st_sensors_set_dataready_irq);
+
+int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale)
+{
+	int err = -EINVAL, i;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	for (i = 0; i < ST_SENSORS_FULLSCALE_AVL_MAX; i++) {
+		if ((sdata->sensor->fs.fs_avl[i].gain == scale) &&
+				(sdata->sensor->fs.fs_avl[i].gain != 0)) {
+			err = 0;
+			break;
+		}
+	}
+	if (err < 0)
+		goto st_sensors_match_scale_error;
+
+	err = st_sensors_set_fullscale(indio_dev,
+					sdata->sensor->fs.fs_avl[i].num);
+
+st_sensors_match_scale_error:
+	return err;
+}
+EXPORT_SYMBOL(st_sensors_set_fullscale_by_gain);
+
+static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
+							u8 ch_addr, int *data)
+{
+	int err;
+	u8 outdata[ST_SENSORS_BYTE_FOR_CHANNEL];
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
+				ch_addr, ST_SENSORS_BYTE_FOR_CHANNEL,
+				outdata, sdata->multiread_bit);
+	if (err < 0)
+		goto read_error;
+
+	*data = (s16)get_unaligned_le16(outdata);
+
+read_error:
+	return err;
+}
+
+int st_sensors_read_info_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *ch, int *val)
+{
+	int err;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	mutex_lock(&indio_dev->mlock);
+	if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+		err = -EBUSY;
+		goto read_error;
+	} else {
+		err = st_sensors_set_enable(indio_dev, true);
+		if (err < 0)
+			goto read_error;
+
+		msleep((sdata->sensor->bootime * 1000) / sdata->odr);
+		err = st_sensors_read_axis_data(indio_dev, ch->address, val);
+		if (err < 0)
+			goto read_error;
+
+		*val = *val >> ch->scan_type.shift;
+	}
+	mutex_unlock(&indio_dev->mlock);
+
+	return err;
+
+read_error:
+	mutex_unlock(&indio_dev->mlock);
+	return err;
+}
+EXPORT_SYMBOL(st_sensors_read_info_raw);
+
+int st_sensors_check_device_support(struct iio_dev *indio_dev,
+			int num_sensors_list, const struct st_sensors *sensors)
+{
+	u8 wai;
+	int i, n, err;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
+					ST_SENSORS_DEFAULT_WAI_ADDRESS, &wai);
+	if (err < 0) {
+		dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n");
+		goto read_wai_error;
+	}
+
+	for (i = 0; i < num_sensors_list; i++) {
+		if (sensors[i].wai == wai)
+			break;
+	}
+	if (i == num_sensors_list)
+		goto device_not_supported;
+
+	for (n = 0; n < ARRAY_SIZE(sensors[i].sensors_supported); n++) {
+		if (strcmp(indio_dev->name,
+				&sensors[i].sensors_supported[n][0]) == 0)
+			break;
+	}
+	if (n == ARRAY_SIZE(sensors[i].sensors_supported)) {
+		dev_err(&indio_dev->dev, "device name and WhoAmI mismatch.\n");
+		goto sensor_name_mismatch;
+	}
+
+	sdata->sensor = (struct st_sensors *)&sensors[i];
+
+	return i;
+
+device_not_supported:
+	dev_err(&indio_dev->dev, "device not supported: WhoAmI (0x%x).\n", wai);
+sensor_name_mismatch:
+	err = -ENODEV;
+read_wai_error:
+	return err;
+}
+EXPORT_SYMBOL(st_sensors_check_device_support);
+
+ssize_t st_sensors_sysfs_get_sampling_frequency(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct st_sensor_data *adata = iio_priv(dev_get_drvdata(dev));
+
+	return sprintf(buf, "%d\n", adata->odr);
+}
+EXPORT_SYMBOL(st_sensors_sysfs_get_sampling_frequency);
+
+ssize_t st_sensors_sysfs_set_sampling_frequency(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	int err;
+	unsigned int odr;
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+
+	err = kstrtoint(buf, 10, &odr);
+	if (err < 0)
+		goto conversion_error;
+
+	mutex_lock(&indio_dev->mlock);
+	err = st_sensors_set_odr(indio_dev, odr);
+	mutex_unlock(&indio_dev->mlock);
+
+conversion_error:
+	return err < 0 ? err : size;
+}
+EXPORT_SYMBOL(st_sensors_sysfs_set_sampling_frequency);
+
+ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+
+	return st_sensors_get_sampling_frequency_avl(indio_dev, buf);
+}
+EXPORT_SYMBOL(st_sensors_sysfs_sampling_frequency_avail);
+
+ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+
+	return st_sensors_get_scale_avl(indio_dev, buf);
+}
+EXPORT_SYMBOL(st_sensors_sysfs_scale_avail);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics ST-sensors core");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c
new file mode 100644
index 0000000..38af944
--- /dev/null
+++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c
@@ -0,0 +1,81 @@
+/*
+ * STMicroelectronics sensors i2c library driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/iio/iio.h>
+
+#include <linux/iio/common/st_sensors_i2c.h>
+
+
+#define ST_SENSORS_I2C_MULTIREAD	0x80
+
+static unsigned int st_sensors_i2c_get_irq(struct iio_dev *indio_dev)
+{
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	return to_i2c_client(sdata->dev)->irq;
+}
+
+static int st_sensors_i2c_read_byte(struct st_sensor_transfer_buffer *tb,
+				struct device *dev, u8 reg_addr, u8 *res_byte)
+{
+	int err;
+
+	err = i2c_smbus_read_byte_data(to_i2c_client(dev), reg_addr);
+	if (err < 0)
+		goto st_accel_i2c_read_byte_error;
+
+	*res_byte = err & 0xff;
+
+st_accel_i2c_read_byte_error:
+	return err < 0 ? err : 0;
+}
+
+static int st_sensors_i2c_read_multiple_byte(
+		struct st_sensor_transfer_buffer *tb, struct device *dev,
+			u8 reg_addr, int len, u8 *data, bool multiread_bit)
+{
+	if (multiread_bit)
+		reg_addr |= ST_SENSORS_I2C_MULTIREAD;
+
+	return i2c_smbus_read_i2c_block_data(to_i2c_client(dev),
+							reg_addr, len, data);
+}
+
+static int st_sensors_i2c_write_byte(struct st_sensor_transfer_buffer *tb,
+				struct device *dev, u8 reg_addr, u8 data)
+{
+	return i2c_smbus_write_byte_data(to_i2c_client(dev), reg_addr, data);
+}
+
+static const struct st_sensor_transfer_function st_sensors_tf_i2c = {
+	.read_byte = st_sensors_i2c_read_byte,
+	.write_byte = st_sensors_i2c_write_byte,
+	.read_multiple_byte = st_sensors_i2c_read_multiple_byte,
+};
+
+void st_sensors_i2c_configure(struct iio_dev *indio_dev,
+		struct i2c_client *client, struct st_sensor_data *sdata)
+{
+	i2c_set_clientdata(client, indio_dev);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->name = client->name;
+
+	sdata->tf = &st_sensors_tf_i2c;
+	sdata->get_irq_data_ready = st_sensors_i2c_get_irq;
+}
+EXPORT_SYMBOL(st_sensors_i2c_configure);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics ST-sensors i2c driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c
new file mode 100644
index 0000000..f0aa2f1
--- /dev/null
+++ b/drivers/iio/common/st_sensors/st_sensors_spi.c
@@ -0,0 +1,128 @@
+/*
+ * STMicroelectronics sensors spi library driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/iio/iio.h>
+
+#include <linux/iio/common/st_sensors_spi.h>
+
+
+#define ST_SENSORS_SPI_MULTIREAD	0xc0
+#define ST_SENSORS_SPI_READ		0x80
+
+static unsigned int st_sensors_spi_get_irq(struct iio_dev *indio_dev)
+{
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	return to_spi_device(sdata->dev)->irq;
+}
+
+static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb,
+	struct device *dev, u8 reg_addr, int len, u8 *data, bool multiread_bit)
+{
+	struct spi_message msg;
+	int err;
+
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = tb->tx_buf,
+			.bits_per_word = 8,
+			.len = 1,
+		},
+		{
+			.rx_buf = tb->rx_buf,
+			.bits_per_word = 8,
+			.len = len,
+		}
+	};
+
+	mutex_lock(&tb->buf_lock);
+	if ((multiread_bit) && (len > 1))
+		tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_MULTIREAD;
+	else
+		tb->tx_buf[0] = reg_addr | ST_SENSORS_SPI_READ;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfers[0], &msg);
+	spi_message_add_tail(&xfers[1], &msg);
+	err = spi_sync(to_spi_device(dev), &msg);
+	if (err)
+		goto acc_spi_read_error;
+
+	memcpy(data, tb->rx_buf, len*sizeof(u8));
+	mutex_unlock(&tb->buf_lock);
+	return len;
+
+acc_spi_read_error:
+	mutex_unlock(&tb->buf_lock);
+	return err;
+}
+
+static int st_sensors_spi_read_byte(struct st_sensor_transfer_buffer *tb,
+				struct device *dev, u8 reg_addr, u8 *res_byte)
+{
+	return st_sensors_spi_read(tb, dev, reg_addr, 1, res_byte, false);
+}
+
+static int st_sensors_spi_read_multiple_byte(
+	struct st_sensor_transfer_buffer *tb, struct device *dev,
+			u8 reg_addr, int len, u8 *data, bool multiread_bit)
+{
+	return st_sensors_spi_read(tb, dev, reg_addr, len, data, multiread_bit);
+}
+
+static int st_sensors_spi_write_byte(struct st_sensor_transfer_buffer *tb,
+				struct device *dev, u8 reg_addr, u8 data)
+{
+	struct spi_message msg;
+	int err;
+
+	struct spi_transfer xfers = {
+		.tx_buf = tb->tx_buf,
+		.bits_per_word = 8,
+		.len = 2,
+	};
+
+	mutex_lock(&tb->buf_lock);
+	tb->tx_buf[0] = reg_addr;
+	tb->tx_buf[1] = data;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfers, &msg);
+	err = spi_sync(to_spi_device(dev), &msg);
+	mutex_unlock(&tb->buf_lock);
+
+	return err;
+}
+
+static const struct st_sensor_transfer_function st_sensors_tf_spi = {
+	.read_byte = st_sensors_spi_read_byte,
+	.write_byte = st_sensors_spi_write_byte,
+	.read_multiple_byte = st_sensors_spi_read_multiple_byte,
+};
+
+void st_sensors_spi_configure(struct iio_dev *indio_dev,
+			struct spi_device *spi, struct st_sensor_data *sdata)
+{
+	spi_set_drvdata(spi, indio_dev);
+
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi->modalias;
+
+	sdata->tf = &st_sensors_tf_spi;
+	sdata->get_irq_data_ready = st_sensors_spi_get_irq;
+}
+EXPORT_SYMBOL(st_sensors_spi_configure);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics ST-sensors spi driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
new file mode 100644
index 0000000..139ed03
--- /dev/null
+++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
@@ -0,0 +1,77 @@
+/*
+ * STMicroelectronics sensors trigger library driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+#include <linux/interrupt.h>
+
+#include <linux/iio/common/st_sensors.h>
+
+
+int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
+				const struct iio_trigger_ops *trigger_ops)
+{
+	int err;
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name);
+	if (sdata->trig == NULL) {
+		err = -ENOMEM;
+		dev_err(&indio_dev->dev, "failed to allocate iio trigger.\n");
+		goto iio_trigger_alloc_error;
+	}
+
+	err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev),
+			iio_trigger_generic_data_rdy_poll,
+			NULL,
+			IRQF_TRIGGER_RISING,
+			sdata->trig->name,
+			sdata->trig);
+	if (err)
+		goto request_irq_error;
+
+	sdata->trig->private_data = indio_dev;
+	sdata->trig->ops = trigger_ops;
+	sdata->trig->dev.parent = sdata->dev;
+
+	err = iio_trigger_register(sdata->trig);
+	if (err < 0) {
+		dev_err(&indio_dev->dev, "failed to register iio trigger.\n");
+		goto iio_trigger_register_error;
+	}
+	indio_dev->trig = sdata->trig;
+
+	return 0;
+
+iio_trigger_register_error:
+	free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig);
+request_irq_error:
+	iio_trigger_free(sdata->trig);
+iio_trigger_alloc_error:
+	return err;
+}
+EXPORT_SYMBOL(st_sensors_allocate_trigger);
+
+void st_sensors_deallocate_trigger(struct iio_dev *indio_dev)
+{
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	iio_trigger_unregister(sdata->trig);
+	free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig);
+	iio_trigger_free(sdata->trig);
+}
+EXPORT_SYMBOL(st_sensors_deallocate_trigger);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics ST-sensors trigger");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 96b68f6..e852a202 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -23,4 +23,34 @@ config HID_SENSOR_GYRO_3D
 	  Say yes here to build support for the HID SENSOR
 	  Gyroscope 3D.
 
+config IIO_ST_GYRO_3AXIS
+	tristate "STMicroelectronics gyroscopes 3-Axis Driver"
+	depends on (I2C || SPI_MASTER) && SYSFS
+	select IIO_ST_SENSORS_CORE
+	select IIO_ST_GYRO_I2C_3AXIS if (I2C)
+	select IIO_ST_GYRO_SPI_3AXIS if (SPI_MASTER)
+	select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
+	select IIO_ST_GYRO_BUFFER if (IIO_TRIGGERED_BUFFER)
+	help
+	  Say yes here to build support for STMicroelectronics gyroscopes:
+	  L3G4200D, LSM330DL, L3GD20, L3GD20H, LSM330DLC, L3G4IS, LSM330.
+
+	  This driver can also be built as a module. If so, will be created
+	  these modules:
+	  - st_gyro (core functions for the driver [it is mandatory]);
+	  - st_gyro_i2c (necessary for the I2C devices [optional*]);
+	  - st_gyro_spi (necessary for the SPI devices [optional*]);
+
+	  (*) one of these is necessary to do something.
+
+config IIO_ST_GYRO_I2C_3AXIS
+	tristate
+	depends on IIO_ST_GYRO_3AXIS
+	depends on IIO_ST_SENSORS_I2C
+
+config IIO_ST_GYRO_SPI_3AXIS
+	tristate
+	depends on IIO_ST_GYRO_3AXIS
+	depends on IIO_ST_SENSORS_SPI
+
 endmenu
diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile
index 702a058..b932f17 100644
--- a/drivers/iio/gyro/Makefile
+++ b/drivers/iio/gyro/Makefile
@@ -4,3 +4,10 @@
 
 obj-$(CONFIG_ADIS16136) += adis16136.o
 obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
+
+obj-$(CONFIG_IIO_ST_GYRO_3AXIS) += st_gyro.o
+st_gyro-y := st_gyro_core.o
+st_gyro-$(CONFIG_IIO_BUFFER) += st_gyro_buffer.o
+
+obj-$(CONFIG_IIO_ST_GYRO_I2C_3AXIS) += st_gyro_i2c.o
+obj-$(CONFIG_IIO_ST_GYRO_SPI_3AXIS) += st_gyro_spi.o
diff --git a/drivers/iio/gyro/st_gyro.h b/drivers/iio/gyro/st_gyro.h
new file mode 100644
index 0000000..3ad9907
--- /dev/null
+++ b/drivers/iio/gyro/st_gyro.h
@@ -0,0 +1,45 @@
+/*
+ * STMicroelectronics gyroscopes driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ * v. 1.0.0
+ * Licensed under the GPL-2.
+ */
+
+#ifndef ST_GYRO_H
+#define ST_GYRO_H
+
+#include <linux/types.h>
+#include <linux/iio/common/st_sensors.h>
+
+#define L3G4200D_GYRO_DEV_NAME		"l3g4200d"
+#define LSM330D_GYRO_DEV_NAME		"lsm330d_gyro"
+#define LSM330DL_GYRO_DEV_NAME		"lsm330dl_gyro"
+#define LSM330DLC_GYRO_DEV_NAME		"lsm330dlc_gyro"
+#define L3GD20_GYRO_DEV_NAME		"l3gd20"
+#define L3GD20H_GYRO_DEV_NAME		"l3gd20h"
+#define L3G4IS_GYRO_DEV_NAME		"l3g4is_ui"
+#define LSM330_GYRO_DEV_NAME		"lsm330_gyro"
+
+int st_gyro_common_probe(struct iio_dev *indio_dev);
+void st_gyro_common_remove(struct iio_dev *indio_dev);
+
+#ifdef CONFIG_IIO_BUFFER
+int st_gyro_allocate_ring(struct iio_dev *indio_dev);
+void st_gyro_deallocate_ring(struct iio_dev *indio_dev);
+int st_gyro_trig_set_state(struct iio_trigger *trig, bool state);
+#define ST_GYRO_TRIGGER_SET_STATE (&st_gyro_trig_set_state)
+#else /* CONFIG_IIO_BUFFER */
+static inline int st_gyro_allocate_ring(struct iio_dev *indio_dev)
+{
+	return 0;
+}
+static inline void st_gyro_deallocate_ring(struct iio_dev *indio_dev)
+{
+}
+#define ST_GYRO_TRIGGER_SET_STATE NULL
+#endif /* CONFIG_IIO_BUFFER */
+
+#endif /* ST_GYRO_H */
diff --git a/drivers/iio/gyro/st_gyro_buffer.c b/drivers/iio/gyro/st_gyro_buffer.c
new file mode 100644
index 0000000..da4d122
--- /dev/null
+++ b/drivers/iio/gyro/st_gyro_buffer.c
@@ -0,0 +1,114 @@
+/*
+ * STMicroelectronics gyroscopes driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/delay.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/common/st_sensors.h>
+#include "st_gyro.h"
+
+int st_gyro_trig_set_state(struct iio_trigger *trig, bool state)
+{
+	struct iio_dev *indio_dev = trig->private_data;
+
+	return st_sensors_set_dataready_irq(indio_dev, state);
+}
+
+static int st_gyro_buffer_preenable(struct iio_dev *indio_dev)
+{
+	int err;
+
+	err = st_sensors_set_enable(indio_dev, true);
+	if (err < 0)
+		goto st_gyro_set_enable_error;
+
+	err = iio_sw_buffer_preenable(indio_dev);
+
+st_gyro_set_enable_error:
+	return err;
+}
+
+static int st_gyro_buffer_postenable(struct iio_dev *indio_dev)
+{
+	int err;
+	struct st_sensor_data *gdata = iio_priv(indio_dev);
+
+	gdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (gdata->buffer_data == NULL) {
+		err = -ENOMEM;
+		goto allocate_memory_error;
+	}
+
+	err = st_sensors_set_axis_enable(indio_dev,
+					(u8)indio_dev->active_scan_mask[0]);
+	if (err < 0)
+		goto st_gyro_buffer_postenable_error;
+
+	err = iio_triggered_buffer_postenable(indio_dev);
+	if (err < 0)
+		goto st_gyro_buffer_postenable_error;
+
+	return err;
+
+st_gyro_buffer_postenable_error:
+	kfree(gdata->buffer_data);
+allocate_memory_error:
+	return err;
+}
+
+static int st_gyro_buffer_predisable(struct iio_dev *indio_dev)
+{
+	int err;
+	struct st_sensor_data *gdata = iio_priv(indio_dev);
+
+	err = iio_triggered_buffer_predisable(indio_dev);
+	if (err < 0)
+		goto st_gyro_buffer_predisable_error;
+
+	err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
+	if (err < 0)
+		goto st_gyro_buffer_predisable_error;
+
+	err = st_sensors_set_enable(indio_dev, false);
+
+st_gyro_buffer_predisable_error:
+	kfree(gdata->buffer_data);
+	return err;
+}
+
+static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = {
+	.preenable = &st_gyro_buffer_preenable,
+	.postenable = &st_gyro_buffer_postenable,
+	.predisable = &st_gyro_buffer_predisable,
+};
+
+int st_gyro_allocate_ring(struct iio_dev *indio_dev)
+{
+	return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+		&st_sensors_trigger_handler, &st_gyro_buffer_setup_ops);
+}
+
+void st_gyro_deallocate_ring(struct iio_dev *indio_dev)
+{
+	iio_triggered_buffer_cleanup(indio_dev);
+}
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics gyroscopes buffer");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
new file mode 100644
index 0000000..0a09998
--- /dev/null
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -0,0 +1,363 @@
+/*
+ * STMicroelectronics gyroscopes driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+
+#include <linux/iio/common/st_sensors.h>
+#include "st_gyro.h"
+
+/* DEFAULT VALUE FOR SENSORS */
+#define ST_GYRO_DEFAULT_OUT_X_L_ADDR		0x28
+#define ST_GYRO_DEFAULT_OUT_Y_L_ADDR		0x2a
+#define ST_GYRO_DEFAULT_OUT_Z_L_ADDR		0x2c
+
+/* FULLSCALE */
+#define ST_GYRO_FS_AVL_250DPS			250
+#define ST_GYRO_FS_AVL_500DPS			500
+#define ST_GYRO_FS_AVL_2000DPS			2000
+
+/* CUSTOM VALUES FOR SENSOR 1 */
+#define ST_GYRO_1_WAI_EXP			0xd3
+#define ST_GYRO_1_ODR_ADDR			0x20
+#define ST_GYRO_1_ODR_MASK			0xc0
+#define ST_GYRO_1_ODR_AVL_100HZ_VAL		0x00
+#define ST_GYRO_1_ODR_AVL_200HZ_VAL		0x01
+#define ST_GYRO_1_ODR_AVL_400HZ_VAL		0x02
+#define ST_GYRO_1_ODR_AVL_800HZ_VAL		0x03
+#define ST_GYRO_1_PW_ADDR			0x20
+#define ST_GYRO_1_PW_MASK			0x08
+#define ST_GYRO_1_FS_ADDR			0x23
+#define ST_GYRO_1_FS_MASK			0x30
+#define ST_GYRO_1_FS_AVL_250_VAL		0x00
+#define ST_GYRO_1_FS_AVL_500_VAL		0x01
+#define ST_GYRO_1_FS_AVL_2000_VAL		0x02
+#define ST_GYRO_1_FS_AVL_250_GAIN		IIO_DEGREE_TO_RAD(8750)
+#define ST_GYRO_1_FS_AVL_500_GAIN		IIO_DEGREE_TO_RAD(17500)
+#define ST_GYRO_1_FS_AVL_2000_GAIN		IIO_DEGREE_TO_RAD(70000)
+#define ST_GYRO_1_BDU_ADDR			0x23
+#define ST_GYRO_1_BDU_MASK			0x80
+#define ST_GYRO_1_DRDY_IRQ_ADDR			0x22
+#define ST_GYRO_1_DRDY_IRQ_MASK			0x08
+#define ST_GYRO_1_MULTIREAD_BIT			true
+
+/* CUSTOM VALUES FOR SENSOR 2 */
+#define ST_GYRO_2_WAI_EXP			0xd4
+#define ST_GYRO_2_ODR_ADDR			0x20
+#define ST_GYRO_2_ODR_MASK			0xc0
+#define ST_GYRO_2_ODR_AVL_95HZ_VAL		0x00
+#define ST_GYRO_2_ODR_AVL_190HZ_VAL		0x01
+#define ST_GYRO_2_ODR_AVL_380HZ_VAL		0x02
+#define ST_GYRO_2_ODR_AVL_760HZ_VAL		0x03
+#define ST_GYRO_2_PW_ADDR			0x20
+#define ST_GYRO_2_PW_MASK			0x08
+#define ST_GYRO_2_FS_ADDR			0x23
+#define ST_GYRO_2_FS_MASK			0x30
+#define ST_GYRO_2_FS_AVL_250_VAL		0x00
+#define ST_GYRO_2_FS_AVL_500_VAL		0x01
+#define ST_GYRO_2_FS_AVL_2000_VAL		0x02
+#define ST_GYRO_2_FS_AVL_250_GAIN		IIO_DEGREE_TO_RAD(8750)
+#define ST_GYRO_2_FS_AVL_500_GAIN		IIO_DEGREE_TO_RAD(17500)
+#define ST_GYRO_2_FS_AVL_2000_GAIN		IIO_DEGREE_TO_RAD(70000)
+#define ST_GYRO_2_BDU_ADDR			0x23
+#define ST_GYRO_2_BDU_MASK			0x80
+#define ST_GYRO_2_DRDY_IRQ_ADDR			0x22
+#define ST_GYRO_2_DRDY_IRQ_MASK			0x08
+#define ST_GYRO_2_MULTIREAD_BIT			true
+
+static const struct iio_chan_spec st_gyro_16bit_channels[] = {
+	ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, ST_SENSORS_SCAN_X,
+		IIO_MOD_X, IIO_LE, ST_SENSORS_DEFAULT_16_REALBITS,
+						ST_GYRO_DEFAULT_OUT_X_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, ST_SENSORS_SCAN_Y,
+		IIO_MOD_Y, IIO_LE, ST_SENSORS_DEFAULT_16_REALBITS,
+						ST_GYRO_DEFAULT_OUT_Y_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL, ST_SENSORS_SCAN_Z,
+		IIO_MOD_Z, IIO_LE, ST_SENSORS_DEFAULT_16_REALBITS,
+						ST_GYRO_DEFAULT_OUT_Z_L_ADDR),
+	IIO_CHAN_SOFT_TIMESTAMP(3)
+};
+
+static const struct st_sensors st_gyro_sensors[] = {
+	{
+		.wai = ST_GYRO_1_WAI_EXP,
+		.sensors_supported = {
+			[0] = L3G4200D_GYRO_DEV_NAME,
+			[1] = LSM330DL_GYRO_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
+		.odr = {
+			.addr = ST_GYRO_1_ODR_ADDR,
+			.mask = ST_GYRO_1_ODR_MASK,
+			.odr_avl = {
+				{ 100, ST_GYRO_1_ODR_AVL_100HZ_VAL, },
+				{ 200, ST_GYRO_1_ODR_AVL_200HZ_VAL, },
+				{ 400, ST_GYRO_1_ODR_AVL_400HZ_VAL, },
+				{ 800, ST_GYRO_1_ODR_AVL_800HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_GYRO_1_PW_ADDR,
+			.mask = ST_GYRO_1_PW_MASK,
+			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
+			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+		},
+		.enable_axis = {
+			.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+		},
+		.fs = {
+			.addr = ST_GYRO_1_FS_ADDR,
+			.mask = ST_GYRO_1_FS_MASK,
+			.fs_avl = {
+				[0] = {
+					.num = ST_GYRO_FS_AVL_250DPS,
+					.value = ST_GYRO_1_FS_AVL_250_VAL,
+					.gain = ST_GYRO_1_FS_AVL_250_GAIN,
+				},
+				[1] = {
+					.num = ST_GYRO_FS_AVL_500DPS,
+					.value = ST_GYRO_1_FS_AVL_500_VAL,
+					.gain = ST_GYRO_1_FS_AVL_500_GAIN,
+				},
+				[2] = {
+					.num = ST_GYRO_FS_AVL_2000DPS,
+					.value = ST_GYRO_1_FS_AVL_2000_VAL,
+					.gain = ST_GYRO_1_FS_AVL_2000_GAIN,
+				},
+			},
+		},
+		.bdu = {
+			.addr = ST_GYRO_1_BDU_ADDR,
+			.mask = ST_GYRO_1_BDU_MASK,
+		},
+		.drdy_irq = {
+			.addr = ST_GYRO_1_DRDY_IRQ_ADDR,
+			.mask = ST_GYRO_1_DRDY_IRQ_MASK,
+		},
+		.multi_read_bit = ST_GYRO_1_MULTIREAD_BIT,
+		.bootime = 2,
+	},
+	{
+		.wai = ST_GYRO_2_WAI_EXP,
+		.sensors_supported = {
+			[0] = L3GD20_GYRO_DEV_NAME,
+			[1] = L3GD20H_GYRO_DEV_NAME,
+			[2] = LSM330D_GYRO_DEV_NAME,
+			[3] = LSM330DLC_GYRO_DEV_NAME,
+			[4] = L3G4IS_GYRO_DEV_NAME,
+			[5] = LSM330_GYRO_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
+		.odr = {
+			.addr = ST_GYRO_2_ODR_ADDR,
+			.mask = ST_GYRO_2_ODR_MASK,
+			.odr_avl = {
+				{ 95, ST_GYRO_2_ODR_AVL_95HZ_VAL, },
+				{ 190, ST_GYRO_2_ODR_AVL_190HZ_VAL, },
+				{ 380, ST_GYRO_2_ODR_AVL_380HZ_VAL, },
+				{ 760, ST_GYRO_2_ODR_AVL_760HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_GYRO_2_PW_ADDR,
+			.mask = ST_GYRO_2_PW_MASK,
+			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
+			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+		},
+		.enable_axis = {
+			.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+		},
+		.fs = {
+			.addr = ST_GYRO_2_FS_ADDR,
+			.mask = ST_GYRO_2_FS_MASK,
+			.fs_avl = {
+				[0] = {
+					.num = ST_GYRO_FS_AVL_250DPS,
+					.value = ST_GYRO_2_FS_AVL_250_VAL,
+					.gain = ST_GYRO_2_FS_AVL_250_GAIN,
+				},
+				[1] = {
+					.num = ST_GYRO_FS_AVL_500DPS,
+					.value = ST_GYRO_2_FS_AVL_500_VAL,
+					.gain = ST_GYRO_2_FS_AVL_500_GAIN,
+				},
+				[2] = {
+					.num = ST_GYRO_FS_AVL_2000DPS,
+					.value = ST_GYRO_2_FS_AVL_2000_VAL,
+					.gain = ST_GYRO_2_FS_AVL_2000_GAIN,
+				},
+			},
+		},
+		.bdu = {
+			.addr = ST_GYRO_2_BDU_ADDR,
+			.mask = ST_GYRO_2_BDU_MASK,
+		},
+		.drdy_irq = {
+			.addr = ST_GYRO_2_DRDY_IRQ_ADDR,
+			.mask = ST_GYRO_2_DRDY_IRQ_MASK,
+		},
+		.multi_read_bit = ST_GYRO_2_MULTIREAD_BIT,
+		.bootime = 2,
+	},
+};
+
+static int st_gyro_read_raw(struct iio_dev *indio_dev,
+			struct iio_chan_spec const *ch, int *val,
+							int *val2, long mask)
+{
+	int err;
+	struct st_sensor_data *gdata = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		err = st_sensors_read_info_raw(indio_dev, ch, val);
+		if (err < 0)
+			goto read_error;
+
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = gdata->current_fullscale->gain;
+		return IIO_VAL_INT_PLUS_MICRO;
+	default:
+		return -EINVAL;
+	}
+
+read_error:
+	return err;
+}
+
+static int st_gyro_write_raw(struct iio_dev *indio_dev,
+		struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+	int err;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
+static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
+static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
+static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_anglvel_scale_available);
+
+static struct attribute *st_gyro_attributes[] = {
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+	&iio_dev_attr_in_anglvel_scale_available.dev_attr.attr,
+	&iio_dev_attr_sampling_frequency.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group st_gyro_attribute_group = {
+	.attrs = st_gyro_attributes,
+};
+
+static const struct iio_info gyro_info = {
+	.driver_module = THIS_MODULE,
+	.attrs = &st_gyro_attribute_group,
+	.read_raw = &st_gyro_read_raw,
+	.write_raw = &st_gyro_write_raw,
+};
+
+static const struct iio_trigger_ops st_gyro_trigger_ops = {
+	.owner = THIS_MODULE,
+	.set_trigger_state = ST_GYRO_TRIGGER_SET_STATE,
+};
+
+int st_gyro_common_probe(struct iio_dev *indio_dev)
+{
+	int err;
+	struct st_sensor_data *gdata = iio_priv(indio_dev);
+
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->info = &gyro_info;
+
+	err = st_sensors_check_device_support(indio_dev,
+				ARRAY_SIZE(st_gyro_sensors), st_gyro_sensors);
+	if (err < 0)
+		goto st_gyro_common_probe_error;
+
+	gdata->multiread_bit = gdata->sensor->multi_read_bit;
+	indio_dev->channels = gdata->sensor->ch;
+	indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
+
+	gdata->current_fullscale = (struct st_sensor_fullscale_avl *)
+						&gdata->sensor->fs.fs_avl[0];
+	gdata->odr = gdata->sensor->odr.odr_avl[0].hz;
+
+	err = st_sensors_init_sensor(indio_dev);
+	if (err < 0)
+		goto st_gyro_common_probe_error;
+
+	if (gdata->get_irq_data_ready(indio_dev) > 0) {
+		err = st_gyro_allocate_ring(indio_dev);
+		if (err < 0)
+			goto st_gyro_common_probe_error;
+
+		err = st_sensors_allocate_trigger(indio_dev,
+							&st_gyro_trigger_ops);
+		if (err < 0)
+			goto st_gyro_probe_trigger_error;
+	}
+
+	err = iio_device_register(indio_dev);
+	if (err)
+		goto st_gyro_device_register_error;
+
+	return err;
+
+st_gyro_device_register_error:
+	if (gdata->get_irq_data_ready(indio_dev) > 0)
+		st_sensors_deallocate_trigger(indio_dev);
+st_gyro_probe_trigger_error:
+	if (gdata->get_irq_data_ready(indio_dev) > 0)
+		st_gyro_deallocate_ring(indio_dev);
+st_gyro_common_probe_error:
+	return err;
+}
+EXPORT_SYMBOL(st_gyro_common_probe);
+
+void st_gyro_common_remove(struct iio_dev *indio_dev)
+{
+	struct st_sensor_data *gdata = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	if (gdata->get_irq_data_ready(indio_dev) > 0) {
+		st_sensors_deallocate_trigger(indio_dev);
+		st_gyro_deallocate_ring(indio_dev);
+	}
+	iio_device_free(indio_dev);
+}
+EXPORT_SYMBOL(st_gyro_common_remove);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics gyroscopes driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
new file mode 100644
index 0000000..a44b5b4
--- /dev/null
+++ b/drivers/iio/gyro/st_gyro_i2c.c
@@ -0,0 +1,85 @@
+/*
+ * STMicroelectronics gyroscopes driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+
+#include <linux/iio/common/st_sensors.h>
+#include <linux/iio/common/st_sensors_i2c.h>
+#include "st_gyro.h"
+
+static int st_gyro_i2c_probe(struct i2c_client *client,
+						const struct i2c_device_id *id)
+{
+	struct iio_dev *indio_dev;
+	struct st_sensor_data *gdata;
+	int err;
+
+	indio_dev = iio_device_alloc(sizeof(*gdata));
+	if (indio_dev == NULL) {
+		err = -ENOMEM;
+		goto iio_device_alloc_error;
+	}
+
+	gdata = iio_priv(indio_dev);
+	gdata->dev = &client->dev;
+
+	st_sensors_i2c_configure(indio_dev, client, gdata);
+
+	err = st_gyro_common_probe(indio_dev);
+	if (err < 0)
+		goto st_gyro_common_probe_error;
+
+	return 0;
+
+st_gyro_common_probe_error:
+	iio_device_free(indio_dev);
+iio_device_alloc_error:
+	return err;
+}
+
+static int st_gyro_i2c_remove(struct i2c_client *client)
+{
+	st_gyro_common_remove(i2c_get_clientdata(client));
+
+	return 0;
+}
+
+static const struct i2c_device_id st_gyro_id_table[] = {
+	{ L3G4200D_GYRO_DEV_NAME },
+	{ LSM330D_GYRO_DEV_NAME },
+	{ LSM330DL_GYRO_DEV_NAME },
+	{ LSM330DLC_GYRO_DEV_NAME },
+	{ L3GD20_GYRO_DEV_NAME },
+	{ L3GD20H_GYRO_DEV_NAME },
+	{ L3G4IS_GYRO_DEV_NAME },
+	{ LSM330_GYRO_DEV_NAME },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, st_gyro_id_table);
+
+static struct i2c_driver st_gyro_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "st-gyro-i2c",
+	},
+	.probe = st_gyro_i2c_probe,
+	.remove = st_gyro_i2c_remove,
+	.id_table = st_gyro_id_table,
+};
+module_i2c_driver(st_gyro_driver);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics gyroscopes i2c driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c
new file mode 100644
index 0000000..8b4dcc5
--- /dev/null
+++ b/drivers/iio/gyro/st_gyro_spi.c
@@ -0,0 +1,84 @@
+/*
+ * STMicroelectronics gyroscopes driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+
+#include <linux/iio/common/st_sensors.h>
+#include <linux/iio/common/st_sensors_spi.h>
+#include "st_gyro.h"
+
+static int st_gyro_spi_probe(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev;
+	struct st_sensor_data *gdata;
+	int err;
+
+	indio_dev = iio_device_alloc(sizeof(*gdata));
+	if (indio_dev == NULL) {
+		err = -ENOMEM;
+		goto iio_device_alloc_error;
+	}
+
+	gdata = iio_priv(indio_dev);
+	gdata->dev = &spi->dev;
+
+	st_sensors_spi_configure(indio_dev, spi, gdata);
+
+	err = st_gyro_common_probe(indio_dev);
+	if (err < 0)
+		goto st_gyro_common_probe_error;
+
+	return 0;
+
+st_gyro_common_probe_error:
+	iio_device_free(indio_dev);
+iio_device_alloc_error:
+	return err;
+}
+
+static int st_gyro_spi_remove(struct spi_device *spi)
+{
+	st_gyro_common_remove(spi_get_drvdata(spi));
+
+	return 0;
+}
+
+static const struct spi_device_id st_gyro_id_table[] = {
+	{ L3G4200D_GYRO_DEV_NAME },
+	{ LSM330D_GYRO_DEV_NAME },
+	{ LSM330DL_GYRO_DEV_NAME },
+	{ LSM330DLC_GYRO_DEV_NAME },
+	{ L3GD20_GYRO_DEV_NAME },
+	{ L3GD20H_GYRO_DEV_NAME },
+	{ L3G4IS_GYRO_DEV_NAME },
+	{ LSM330_GYRO_DEV_NAME },
+	{},
+};
+MODULE_DEVICE_TABLE(spi, st_gyro_id_table);
+
+static struct spi_driver st_gyro_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "st-gyro-spi",
+	},
+	.probe = st_gyro_spi_probe,
+	.remove = st_gyro_spi_remove,
+	.id_table = st_gyro_id_table,
+};
+module_spi_driver(st_gyro_driver);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics gyroscopes spi driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 3d79a40..723563b 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -25,3 +25,5 @@ config IIO_ADIS_LIB_BUFFER
 	help
 	  A set of buffer helper functions for the Analog Devices ADIS* device
 	  family.
+
+source "drivers/iio/imu/inv_mpu6050/Kconfig"
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index cfe5763..1b41584 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -8,3 +8,5 @@ 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
+
+obj-y += inv_mpu6050/
diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig
new file mode 100644
index 0000000..361b232
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/Kconfig
@@ -0,0 +1,14 @@
+#
+# inv-mpu6050 drivers for Invensense MPU devices and combos
+#
+
+config INV_MPU6050_IIO
+	tristate "Invensense MPU6050 devices"
+	depends on I2C && SYSFS
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  This driver supports the Invensense MPU6050 devices.
+	  It is a gyroscope/accelerometer combo device.
+	  This driver can be built as a module. The module will be called
+	  inv-mpu6050.
diff --git a/drivers/iio/imu/inv_mpu6050/Makefile b/drivers/iio/imu/inv_mpu6050/Makefile
new file mode 100644
index 0000000..3a677c7
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Invensense MPU6050 device.
+#
+
+obj-$(CONFIG_INV_MPU6050_IIO) += inv-mpu6050.o
+inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
new file mode 100644
index 0000000..37ca05b
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -0,0 +1,795 @@
+/*
+* Copyright (C) 2012 Invensense, 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.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+#include <linux/jiffies.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kfifo.h>
+#include <linux/spinlock.h>
+#include "inv_mpu_iio.h"
+
+/*
+ * this is the gyro scale translated from dynamic range plus/minus
+ * {250, 500, 1000, 2000} to rad/s
+ */
+static const int gyro_scale_6050[] = {133090, 266181, 532362, 1064724};
+
+/*
+ * this is the accel scale translated from dynamic range plus/minus
+ * {2, 4, 8, 16} to m/s^2
+ */
+static const int accel_scale[] = {598, 1196, 2392, 4785};
+
+static const struct inv_mpu6050_reg_map reg_set_6050 = {
+	.sample_rate_div	= INV_MPU6050_REG_SAMPLE_RATE_DIV,
+	.lpf                    = INV_MPU6050_REG_CONFIG,
+	.user_ctrl              = INV_MPU6050_REG_USER_CTRL,
+	.fifo_en                = INV_MPU6050_REG_FIFO_EN,
+	.gyro_config            = INV_MPU6050_REG_GYRO_CONFIG,
+	.accl_config            = INV_MPU6050_REG_ACCEL_CONFIG,
+	.fifo_count_h           = INV_MPU6050_REG_FIFO_COUNT_H,
+	.fifo_r_w               = INV_MPU6050_REG_FIFO_R_W,
+	.raw_gyro               = INV_MPU6050_REG_RAW_GYRO,
+	.raw_accl               = INV_MPU6050_REG_RAW_ACCEL,
+	.temperature            = INV_MPU6050_REG_TEMPERATURE,
+	.int_enable             = INV_MPU6050_REG_INT_ENABLE,
+	.pwr_mgmt_1             = INV_MPU6050_REG_PWR_MGMT_1,
+	.pwr_mgmt_2             = INV_MPU6050_REG_PWR_MGMT_2,
+};
+
+static const struct inv_mpu6050_chip_config chip_config_6050 = {
+	.fsr = INV_MPU6050_FSR_2000DPS,
+	.lpf = INV_MPU6050_FILTER_20HZ,
+	.fifo_rate = INV_MPU6050_INIT_FIFO_RATE,
+	.gyro_fifo_enable = false,
+	.accl_fifo_enable = false,
+	.accl_fs = INV_MPU6050_FS_02G,
+};
+
+static const struct inv_mpu6050_hw hw_info[INV_NUM_PARTS] = {
+	{
+		.num_reg = 117,
+		.name = "MPU6050",
+		.reg = &reg_set_6050,
+		.config = &chip_config_6050,
+	},
+};
+
+int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 d)
+{
+	return i2c_smbus_write_i2c_block_data(st->client, reg, 1, &d);
+}
+
+int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
+{
+	u8 d, mgmt_1;
+	int result;
+
+	/* switch clock needs to be careful. Only when gyro is on, can
+	   clock source be switched to gyro. Otherwise, it must be set to
+	   internal clock */
+	if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) {
+		result = i2c_smbus_read_i2c_block_data(st->client,
+				       st->reg->pwr_mgmt_1, 1, &mgmt_1);
+		if (result != 1)
+			return result;
+
+		mgmt_1 &= ~INV_MPU6050_BIT_CLK_MASK;
+	}
+
+	if ((INV_MPU6050_BIT_PWR_GYRO_STBY == mask) && (!en)) {
+		/* turning off gyro requires switch to internal clock first.
+		   Then turn off gyro engine */
+		mgmt_1 |= INV_CLK_INTERNAL;
+		result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, mgmt_1);
+		if (result)
+			return result;
+	}
+
+	result = i2c_smbus_read_i2c_block_data(st->client,
+				       st->reg->pwr_mgmt_2, 1, &d);
+	if (result != 1)
+		return result;
+	if (en)
+		d &= ~mask;
+	else
+		d |= mask;
+	result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_2, d);
+	if (result)
+		return result;
+
+	if (en) {
+		/* Wait for output stablize */
+		msleep(INV_MPU6050_TEMP_UP_TIME);
+		if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) {
+			/* switch internal clock to PLL */
+			mgmt_1 |= INV_CLK_PLL;
+			result = inv_mpu6050_write_reg(st,
+					st->reg->pwr_mgmt_1, mgmt_1);
+			if (result)
+				return result;
+		}
+	}
+
+	return 0;
+}
+
+int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
+{
+	int result;
+
+	if (power_on)
+		result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, 0);
+	else
+		result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
+						INV_MPU6050_BIT_SLEEP);
+	if (result)
+		return result;
+
+	if (power_on)
+		msleep(INV_MPU6050_REG_UP_TIME);
+
+	return 0;
+}
+
+/**
+ *  inv_mpu6050_init_config() - Initialize hardware, disable FIFO.
+ *
+ *  Initial configuration:
+ *  FSR: ± 2000DPS
+ *  DLPF: 20Hz
+ *  FIFO rate: 50Hz
+ *  Clock source: Gyro PLL
+ */
+static int inv_mpu6050_init_config(struct iio_dev *indio_dev)
+{
+	int result;
+	u8 d;
+	struct inv_mpu6050_state *st = iio_priv(indio_dev);
+
+	result = inv_mpu6050_set_power_itg(st, true);
+	if (result)
+		return result;
+	d = (INV_MPU6050_FSR_2000DPS << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
+	result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d);
+	if (result)
+		return result;
+
+	d = INV_MPU6050_FILTER_20HZ;
+	result = inv_mpu6050_write_reg(st, st->reg->lpf, d);
+	if (result)
+		return result;
+
+	d = INV_MPU6050_ONE_K_HZ / INV_MPU6050_INIT_FIFO_RATE - 1;
+	result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d);
+	if (result)
+		return result;
+
+	d = (INV_MPU6050_FS_02G << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
+	result = inv_mpu6050_write_reg(st, st->reg->accl_config, d);
+	if (result)
+		return result;
+
+	memcpy(&st->chip_config, hw_info[st->chip_type].config,
+		sizeof(struct inv_mpu6050_chip_config));
+	result = inv_mpu6050_set_power_itg(st, false);
+
+	return result;
+}
+
+static int inv_mpu6050_sensor_show(struct inv_mpu6050_state  *st, int reg,
+				int axis, int *val)
+{
+	int ind, result;
+	__be16 d;
+
+	ind = (axis - IIO_MOD_X) * 2;
+	result = i2c_smbus_read_i2c_block_data(st->client, reg + ind,  2,
+						(u8 *)&d);
+	if (result != 2)
+		return -EINVAL;
+	*val = (short)be16_to_cpup(&d);
+
+	return IIO_VAL_INT;
+}
+
+static int inv_mpu6050_read_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int *val,
+			      int *val2,
+			      long mask) {
+	struct inv_mpu6050_state  *st = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+	{
+		int ret, result;
+
+		ret = IIO_VAL_INT;
+		result = 0;
+		mutex_lock(&indio_dev->mlock);
+		if (!st->chip_config.enable) {
+			result = inv_mpu6050_set_power_itg(st, true);
+			if (result)
+				goto error_read_raw;
+		}
+		/* when enable is on, power is already on */
+		switch (chan->type) {
+		case IIO_ANGL_VEL:
+			if (!st->chip_config.gyro_fifo_enable ||
+					!st->chip_config.enable) {
+				result = inv_mpu6050_switch_engine(st, true,
+						INV_MPU6050_BIT_PWR_GYRO_STBY);
+				if (result)
+					goto error_read_raw;
+			}
+			ret =  inv_mpu6050_sensor_show(st, st->reg->raw_gyro,
+						chan->channel2, val);
+			if (!st->chip_config.gyro_fifo_enable ||
+					!st->chip_config.enable) {
+				result = inv_mpu6050_switch_engine(st, false,
+						INV_MPU6050_BIT_PWR_GYRO_STBY);
+				if (result)
+					goto error_read_raw;
+			}
+			break;
+		case IIO_ACCEL:
+			if (!st->chip_config.accl_fifo_enable ||
+					!st->chip_config.enable) {
+				result = inv_mpu6050_switch_engine(st, true,
+						INV_MPU6050_BIT_PWR_ACCL_STBY);
+				if (result)
+					goto error_read_raw;
+			}
+			ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,
+						chan->channel2, val);
+			if (!st->chip_config.accl_fifo_enable ||
+					!st->chip_config.enable) {
+				result = inv_mpu6050_switch_engine(st, false,
+						INV_MPU6050_BIT_PWR_ACCL_STBY);
+				if (result)
+					goto error_read_raw;
+			}
+			break;
+		case IIO_TEMP:
+			/* wait for stablization */
+			msleep(INV_MPU6050_SENSOR_UP_TIME);
+			inv_mpu6050_sensor_show(st, st->reg->temperature,
+							IIO_MOD_X, val);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+error_read_raw:
+		if (!st->chip_config.enable)
+			result |= inv_mpu6050_set_power_itg(st, false);
+		mutex_unlock(&indio_dev->mlock);
+		if (result)
+			return result;
+
+		return ret;
+	}
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_ANGL_VEL:
+			*val  = 0;
+			*val2 = gyro_scale_6050[st->chip_config.fsr];
+
+			return IIO_VAL_INT_PLUS_NANO;
+		case IIO_ACCEL:
+			*val = 0;
+			*val2 = accel_scale[st->chip_config.accl_fs];
+
+			return IIO_VAL_INT_PLUS_MICRO;
+		case IIO_TEMP:
+			*val = 0;
+			*val2 = INV_MPU6050_TEMP_SCALE;
+
+			return IIO_VAL_INT_PLUS_MICRO;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_OFFSET:
+		switch (chan->type) {
+		case IIO_TEMP:
+			*val = INV_MPU6050_TEMP_OFFSET;
+
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	default:
+		return -EINVAL;
+	}
+}
+
+static int inv_mpu6050_write_fsr(struct inv_mpu6050_state *st, int fsr)
+{
+	int result;
+	u8 d;
+
+	if (fsr < 0 || fsr > INV_MPU6050_MAX_GYRO_FS_PARAM)
+		return -EINVAL;
+	if (fsr == st->chip_config.fsr)
+		return 0;
+
+	d = (fsr << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
+	result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d);
+	if (result)
+		return result;
+	st->chip_config.fsr = fsr;
+
+	return 0;
+}
+
+static int inv_mpu6050_write_accel_fs(struct inv_mpu6050_state *st, int fs)
+{
+	int result;
+	u8 d;
+
+	if (fs < 0 || fs > INV_MPU6050_MAX_ACCL_FS_PARAM)
+		return -EINVAL;
+	if (fs == st->chip_config.accl_fs)
+		return 0;
+
+	d = (fs << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
+	result = inv_mpu6050_write_reg(st, st->reg->accl_config, d);
+	if (result)
+		return result;
+	st->chip_config.accl_fs = fs;
+
+	return 0;
+}
+
+static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val,
+			       int val2,
+			       long mask) {
+	struct inv_mpu6050_state  *st = iio_priv(indio_dev);
+	int result;
+
+	mutex_lock(&indio_dev->mlock);
+	/* we should only update scale when the chip is disabled, i.e.,
+		not running */
+	if (st->chip_config.enable) {
+		result = -EBUSY;
+		goto error_write_raw;
+	}
+	result = inv_mpu6050_set_power_itg(st, true);
+	if (result)
+		goto error_write_raw;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_ANGL_VEL:
+			result = inv_mpu6050_write_fsr(st, val);
+			break;
+		case IIO_ACCEL:
+			result = inv_mpu6050_write_accel_fs(st, val);
+			break;
+		default:
+			result = -EINVAL;
+			break;
+		}
+		break;
+	default:
+		result = -EINVAL;
+		break;
+	}
+
+error_write_raw:
+	result |= inv_mpu6050_set_power_itg(st, false);
+	mutex_unlock(&indio_dev->mlock);
+
+	return result;
+}
+
+/**
+ *  inv_mpu6050_set_lpf() - set low pass filer based on fifo rate.
+ *
+ *                  Based on the Nyquist principle, the sampling rate must
+ *                  exceed twice of the bandwidth of the signal, or there
+ *                  would be alising. This function basically search for the
+ *                  correct low pass parameters based on the fifo rate, e.g,
+ *                  sampling frequency.
+ */
+static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate)
+{
+	const int hz[] = {188, 98, 42, 20, 10, 5};
+	const int d[] = {INV_MPU6050_FILTER_188HZ, INV_MPU6050_FILTER_98HZ,
+			INV_MPU6050_FILTER_42HZ, INV_MPU6050_FILTER_20HZ,
+			INV_MPU6050_FILTER_10HZ, INV_MPU6050_FILTER_5HZ};
+	int i, h, result;
+	u8 data;
+
+	h = (rate >> 1);
+	i = 0;
+	while ((h < hz[i]) && (i < ARRAY_SIZE(d) - 1))
+		i++;
+	data = d[i];
+	result = inv_mpu6050_write_reg(st, st->reg->lpf, data);
+	if (result)
+		return result;
+	st->chip_config.lpf = data;
+
+	return 0;
+}
+
+/**
+ * inv_mpu6050_fifo_rate_store() - Set fifo rate.
+ */
+static ssize_t inv_mpu6050_fifo_rate_store(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t count)
+{
+	s32 fifo_rate;
+	u8 d;
+	int result;
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct inv_mpu6050_state *st = iio_priv(indio_dev);
+
+	if (kstrtoint(buf, 10, &fifo_rate))
+		return -EINVAL;
+	if (fifo_rate < INV_MPU6050_MIN_FIFO_RATE ||
+				fifo_rate > INV_MPU6050_MAX_FIFO_RATE)
+		return -EINVAL;
+	if (fifo_rate == st->chip_config.fifo_rate)
+		return count;
+
+	mutex_lock(&indio_dev->mlock);
+	if (st->chip_config.enable) {
+		result = -EBUSY;
+		goto fifo_rate_fail;
+	}
+	result = inv_mpu6050_set_power_itg(st, true);
+	if (result)
+		goto fifo_rate_fail;
+
+	d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1;
+	result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d);
+	if (result)
+		goto fifo_rate_fail;
+	st->chip_config.fifo_rate = fifo_rate;
+
+	result = inv_mpu6050_set_lpf(st, fifo_rate);
+	if (result)
+		goto fifo_rate_fail;
+
+fifo_rate_fail:
+	result |= inv_mpu6050_set_power_itg(st, false);
+	mutex_unlock(&indio_dev->mlock);
+	if (result)
+		return result;
+
+	return count;
+}
+
+/**
+ * inv_fifo_rate_show() - Get the current sampling rate.
+ */
+static ssize_t inv_fifo_rate_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev));
+
+	return sprintf(buf, "%d\n", st->chip_config.fifo_rate);
+}
+
+/**
+ * inv_attr_show() - calling this function will show current
+ *                    parameters.
+ */
+static ssize_t inv_attr_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev));
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	s8 *m;
+
+	switch (this_attr->address) {
+	/* In MPU6050, the two matrix are the same because gyro and accel
+	   are integrated in one chip */
+	case ATTR_GYRO_MATRIX:
+	case ATTR_ACCL_MATRIX:
+		m = st->plat_data.orientation;
+
+		return sprintf(buf, "%d, %d, %d; %d, %d, %d; %d, %d, %d\n",
+			m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
+	default:
+		return -EINVAL;
+	}
+}
+
+/**
+ * inv_mpu6050_validate_trigger() - validate_trigger callback for invensense
+ *                                  MPU6050 device.
+ * @indio_dev: The IIO device
+ * @trig: The new trigger
+ *
+ * Returns: 0 if the 'trig' matches the trigger registered by the MPU6050
+ * device, -EINVAL otherwise.
+ */
+static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev,
+					struct iio_trigger *trig)
+{
+	struct inv_mpu6050_state *st = iio_priv(indio_dev);
+
+	if (st->trig != trig)
+		return -EINVAL;
+
+	return 0;
+}
+
+#define INV_MPU6050_CHAN(_type, _channel2, _index)                    \
+	{                                                             \
+		.type = _type,                                        \
+		.modified = 1,                                        \
+		.channel2 = _channel2,                                \
+		.info_mask =  IIO_CHAN_INFO_SCALE_SHARED_BIT          \
+				| IIO_CHAN_INFO_RAW_SEPARATE_BIT,     \
+		.scan_index = _index,                                 \
+		.scan_type = {                                        \
+				.sign = 's',                          \
+				.realbits = 16,                       \
+				.storagebits = 16,                    \
+				.shift = 0 ,                          \
+				.endianness = IIO_BE,                 \
+			     },                                       \
+	}
+
+static const struct iio_chan_spec inv_mpu_channels[] = {
+	IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP),
+	/*
+	 * Note that temperature should only be via polled reading only,
+	 * not the final scan elements output.
+	 */
+	{
+		.type = IIO_TEMP,
+		.info_mask =  IIO_CHAN_INFO_RAW_SEPARATE_BIT
+				| IIO_CHAN_INFO_OFFSET_SEPARATE_BIT
+				| IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+		.scan_index = -1,
+	},
+	INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X),
+	INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y),
+	INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z),
+
+	INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X),
+	INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y),
+	INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
+};
+
+/* constant IIO attribute */
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 20 50 100 200 500");
+static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, inv_fifo_rate_show,
+	inv_mpu6050_fifo_rate_store);
+static IIO_DEVICE_ATTR(in_gyro_matrix, S_IRUGO, inv_attr_show, NULL,
+	ATTR_GYRO_MATRIX);
+static IIO_DEVICE_ATTR(in_accel_matrix, S_IRUGO, inv_attr_show, NULL,
+	ATTR_ACCL_MATRIX);
+
+static struct attribute *inv_attributes[] = {
+	&iio_dev_attr_in_gyro_matrix.dev_attr.attr,
+	&iio_dev_attr_in_accel_matrix.dev_attr.attr,
+	&iio_dev_attr_sampling_frequency.dev_attr.attr,
+	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group inv_attribute_group = {
+	.attrs = inv_attributes
+};
+
+static const struct iio_info mpu_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = &inv_mpu6050_read_raw,
+	.write_raw = &inv_mpu6050_write_raw,
+	.attrs = &inv_attribute_group,
+	.validate_trigger = inv_mpu6050_validate_trigger,
+};
+
+/**
+ *  inv_check_and_setup_chip() - check and setup chip.
+ */
+static int inv_check_and_setup_chip(struct inv_mpu6050_state *st,
+		const struct i2c_device_id *id)
+{
+	int result;
+
+	st->chip_type = INV_MPU6050;
+	st->hw  = &hw_info[st->chip_type];
+	st->reg = hw_info[st->chip_type].reg;
+
+	/* reset to make sure previous state are not there */
+	result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
+					INV_MPU6050_BIT_H_RESET);
+	if (result)
+		return result;
+	msleep(INV_MPU6050_POWER_UP_TIME);
+	/* toggle power state. After reset, the sleep bit could be on
+		or off depending on the OTP settings. Toggling power would
+		make it in a definite state as well as making the hardware
+		state align with the software state */
+	result = inv_mpu6050_set_power_itg(st, false);
+	if (result)
+		return result;
+	result = inv_mpu6050_set_power_itg(st, true);
+	if (result)
+		return result;
+
+	result = inv_mpu6050_switch_engine(st, false,
+					INV_MPU6050_BIT_PWR_ACCL_STBY);
+	if (result)
+		return result;
+	result = inv_mpu6050_switch_engine(st, false,
+					INV_MPU6050_BIT_PWR_GYRO_STBY);
+	if (result)
+		return result;
+
+	return 0;
+}
+
+/**
+ *  inv_mpu_probe() - probe function.
+ *  @client:          i2c client.
+ *  @id:              i2c device id.
+ *
+ *  Returns 0 on success, a negative error code otherwise.
+ */
+static int inv_mpu_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	struct inv_mpu6050_state *st;
+	struct iio_dev *indio_dev;
+	int result;
+
+	if (!i2c_check_functionality(client->adapter,
+					I2C_FUNC_SMBUS_READ_I2C_BLOCK |
+					I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
+		result = -ENOSYS;
+		goto out_no_free;
+	}
+	indio_dev = iio_device_alloc(sizeof(*st));
+	if (indio_dev == NULL) {
+		result =  -ENOMEM;
+		goto out_no_free;
+	}
+	st = iio_priv(indio_dev);
+	st->client = client;
+	st->plat_data = *(struct inv_mpu6050_platform_data
+				*)dev_get_platdata(&client->dev);
+	/* power is turned on inside check chip type*/
+	result = inv_check_and_setup_chip(st, id);
+	if (result)
+		goto out_free;
+
+	result = inv_mpu6050_init_config(indio_dev);
+	if (result) {
+		dev_err(&client->dev,
+			"Could not initialize device.\n");
+		goto out_free;
+	}
+
+	i2c_set_clientdata(client, indio_dev);
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->name = id->name;
+	indio_dev->channels = inv_mpu_channels;
+	indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
+
+	indio_dev->info = &mpu_info;
+	indio_dev->modes = INDIO_BUFFER_TRIGGERED;
+
+	result = iio_triggered_buffer_setup(indio_dev,
+					    inv_mpu6050_irq_handler,
+					    inv_mpu6050_read_fifo,
+					    NULL);
+	if (result) {
+		dev_err(&st->client->dev, "configure buffer fail %d\n",
+				result);
+		goto out_free;
+	}
+	result = inv_mpu6050_probe_trigger(indio_dev);
+	if (result) {
+		dev_err(&st->client->dev, "trigger probe fail %d\n", result);
+		goto out_unreg_ring;
+	}
+
+	INIT_KFIFO(st->timestamps);
+	spin_lock_init(&st->time_stamp_lock);
+	result = iio_device_register(indio_dev);
+	if (result) {
+		dev_err(&st->client->dev, "IIO register fail %d\n", result);
+		goto out_remove_trigger;
+	}
+
+	return 0;
+
+out_remove_trigger:
+	inv_mpu6050_remove_trigger(st);
+out_unreg_ring:
+	iio_triggered_buffer_cleanup(indio_dev);
+out_free:
+	iio_device_free(indio_dev);
+out_no_free:
+
+	return result;
+}
+
+static int inv_mpu_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct inv_mpu6050_state *st = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	inv_mpu6050_remove_trigger(st);
+	iio_triggered_buffer_cleanup(indio_dev);
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+#ifdef CONFIG_PM_SLEEP
+
+static int inv_mpu_resume(struct device *dev)
+{
+	return inv_mpu6050_set_power_itg(
+		iio_priv(i2c_get_clientdata(to_i2c_client(dev))), true);
+}
+
+static int inv_mpu_suspend(struct device *dev)
+{
+	return inv_mpu6050_set_power_itg(
+		iio_priv(i2c_get_clientdata(to_i2c_client(dev))), false);
+}
+static SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume);
+
+#define INV_MPU6050_PMOPS (&inv_mpu_pmops)
+#else
+#define INV_MPU6050_PMOPS NULL
+#endif /* CONFIG_PM_SLEEP */
+
+/*
+ * device id table is used to identify what device can be
+ * supported by this driver
+ */
+static const struct i2c_device_id inv_mpu_id[] = {
+	{"mpu6050", INV_MPU6050},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, inv_mpu_id);
+
+static struct i2c_driver inv_mpu_driver = {
+	.probe		=	inv_mpu_probe,
+	.remove		=	inv_mpu_remove,
+	.id_table	=	inv_mpu_id,
+	.driver = {
+		.owner	=	THIS_MODULE,
+		.name	=	"inv-mpu6050",
+		.pm     =       INV_MPU6050_PMOPS,
+	},
+};
+
+module_i2c_driver(inv_mpu_driver);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Invensense device MPU6050 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
new file mode 100644
index 0000000..f383955
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -0,0 +1,246 @@
+/*
+* Copyright (C) 2012 Invensense, 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.
+*/
+#include <linux/i2c.h>
+#include <linux/kfifo.h>
+#include <linux/spinlock.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/platform_data/invensense_mpu6050.h>
+
+/**
+ *  struct inv_mpu6050_reg_map - Notable registers.
+ *  @sample_rate_div:	Divider applied to gyro output rate.
+ *  @lpf:		Configures internal low pass filter.
+ *  @user_ctrl:		Enables/resets the FIFO.
+ *  @fifo_en:		Determines which data will appear in FIFO.
+ *  @gyro_config:	gyro config register.
+ *  @accl_config:	accel config register
+ *  @fifo_count_h:	Upper byte of FIFO count.
+ *  @fifo_r_w:		FIFO register.
+ *  @raw_gyro:		Address of first gyro register.
+ *  @raw_accl:		Address of first accel register.
+ *  @temperature:	temperature register
+ *  @int_enable:	Interrupt enable register.
+ *  @pwr_mgmt_1:	Controls chip's power state and clock source.
+ *  @pwr_mgmt_2:	Controls power state of individual sensors.
+ */
+struct inv_mpu6050_reg_map {
+	u8 sample_rate_div;
+	u8 lpf;
+	u8 user_ctrl;
+	u8 fifo_en;
+	u8 gyro_config;
+	u8 accl_config;
+	u8 fifo_count_h;
+	u8 fifo_r_w;
+	u8 raw_gyro;
+	u8 raw_accl;
+	u8 temperature;
+	u8 int_enable;
+	u8 pwr_mgmt_1;
+	u8 pwr_mgmt_2;
+};
+
+/*device enum */
+enum inv_devices {
+	INV_MPU6050,
+	INV_NUM_PARTS
+};
+
+/**
+ *  struct inv_mpu6050_chip_config - Cached chip configuration data.
+ *  @fsr:		Full scale range.
+ *  @lpf:		Digital low pass filter frequency.
+ *  @accl_fs:		accel full scale range.
+ *  @enable:		master enable state.
+ *  @accl_fifo_enable:	enable accel data output
+ *  @gyro_fifo_enable:	enable gyro data output
+ *  @fifo_rate:		FIFO update rate.
+ */
+struct inv_mpu6050_chip_config {
+	unsigned int fsr:2;
+	unsigned int lpf:3;
+	unsigned int accl_fs:2;
+	unsigned int enable:1;
+	unsigned int accl_fifo_enable:1;
+	unsigned int gyro_fifo_enable:1;
+	u16 fifo_rate;
+};
+
+/**
+ *  struct inv_mpu6050_hw - Other important hardware information.
+ *  @num_reg:	Number of registers on device.
+ *  @name:      name of the chip.
+ *  @reg:   register map of the chip.
+ *  @config:    configuration of the chip.
+ */
+struct inv_mpu6050_hw {
+	u8 num_reg;
+	u8 *name;
+	const struct inv_mpu6050_reg_map *reg;
+	const struct inv_mpu6050_chip_config *config;
+};
+
+/*
+ *  struct inv_mpu6050_state - Driver state variables.
+ *  @TIMESTAMP_FIFO_SIZE: fifo size for timestamp.
+ *  @trig:              IIO trigger.
+ *  @chip_config:	Cached attribute information.
+ *  @reg:		Map of important registers.
+ *  @hw:		Other hardware-specific information.
+ *  @chip_type:		chip type.
+ *  @time_stamp_lock:	spin lock to time stamp.
+ *  @client:		i2c client handle.
+ *  @plat_data:		platform data.
+ *  @timestamps:        kfifo queue to store time stamp.
+ */
+struct inv_mpu6050_state {
+#define TIMESTAMP_FIFO_SIZE 16
+	struct iio_trigger  *trig;
+	struct inv_mpu6050_chip_config chip_config;
+	const struct inv_mpu6050_reg_map *reg;
+	const struct inv_mpu6050_hw *hw;
+	enum   inv_devices chip_type;
+	spinlock_t time_stamp_lock;
+	struct i2c_client *client;
+	struct inv_mpu6050_platform_data plat_data;
+	DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
+};
+
+/*register and associated bit definition*/
+#define INV_MPU6050_REG_SAMPLE_RATE_DIV     0x19
+#define INV_MPU6050_REG_CONFIG              0x1A
+#define INV_MPU6050_REG_GYRO_CONFIG         0x1B
+#define INV_MPU6050_REG_ACCEL_CONFIG	    0x1C
+
+#define INV_MPU6050_REG_FIFO_EN             0x23
+#define INV_MPU6050_BIT_ACCEL_OUT                   0x08
+#define INV_MPU6050_BITS_GYRO_OUT                   0x70
+
+#define INV_MPU6050_REG_INT_ENABLE          0x38
+#define INV_MPU6050_BIT_DATA_RDY_EN                 0x01
+#define INV_MPU6050_BIT_DMP_INT_EN                  0x02
+
+#define INV_MPU6050_REG_RAW_ACCEL           0x3B
+#define INV_MPU6050_REG_TEMPERATURE         0x41
+#define INV_MPU6050_REG_RAW_GYRO            0x43
+
+#define INV_MPU6050_REG_USER_CTRL           0x6A
+#define INV_MPU6050_BIT_FIFO_RST                    0x04
+#define INV_MPU6050_BIT_DMP_RST                     0x08
+#define INV_MPU6050_BIT_I2C_MST_EN                  0x20
+#define INV_MPU6050_BIT_FIFO_EN                     0x40
+#define INV_MPU6050_BIT_DMP_EN                      0x80
+
+#define INV_MPU6050_REG_PWR_MGMT_1          0x6B
+#define INV_MPU6050_BIT_H_RESET                     0x80
+#define INV_MPU6050_BIT_SLEEP                       0x40
+#define INV_MPU6050_BIT_CLK_MASK                    0x7
+
+#define INV_MPU6050_REG_PWR_MGMT_2          0x6C
+#define INV_MPU6050_BIT_PWR_ACCL_STBY               0x38
+#define INV_MPU6050_BIT_PWR_GYRO_STBY               0x07
+
+#define INV_MPU6050_REG_FIFO_COUNT_H        0x72
+#define INV_MPU6050_REG_FIFO_R_W            0x74
+
+#define INV_MPU6050_BYTES_PER_3AXIS_SENSOR   6
+#define INV_MPU6050_FIFO_COUNT_BYTE          2
+#define INV_MPU6050_FIFO_THRESHOLD           500
+#define INV_MPU6050_POWER_UP_TIME            100
+#define INV_MPU6050_TEMP_UP_TIME             100
+#define INV_MPU6050_SENSOR_UP_TIME           30
+#define INV_MPU6050_REG_UP_TIME              5
+
+#define INV_MPU6050_TEMP_OFFSET	             12421
+#define INV_MPU6050_TEMP_SCALE               2941
+#define INV_MPU6050_MAX_GYRO_FS_PARAM        3
+#define INV_MPU6050_MAX_ACCL_FS_PARAM        3
+#define INV_MPU6050_THREE_AXIS               3
+#define INV_MPU6050_GYRO_CONFIG_FSR_SHIFT    3
+#define INV_MPU6050_ACCL_CONFIG_FSR_SHIFT    3
+
+/* 6 + 6 round up and plus 8 */
+#define INV_MPU6050_OUTPUT_DATA_SIZE         24
+
+/* init parameters */
+#define INV_MPU6050_INIT_FIFO_RATE           50
+#define INV_MPU6050_TIME_STAMP_TOR                        5
+#define INV_MPU6050_MAX_FIFO_RATE                         1000
+#define INV_MPU6050_MIN_FIFO_RATE                         4
+#define INV_MPU6050_ONE_K_HZ                              1000
+
+/* scan element definition */
+enum inv_mpu6050_scan {
+	INV_MPU6050_SCAN_ACCL_X,
+	INV_MPU6050_SCAN_ACCL_Y,
+	INV_MPU6050_SCAN_ACCL_Z,
+	INV_MPU6050_SCAN_GYRO_X,
+	INV_MPU6050_SCAN_GYRO_Y,
+	INV_MPU6050_SCAN_GYRO_Z,
+	INV_MPU6050_SCAN_TIMESTAMP,
+};
+
+enum inv_mpu6050_filter_e {
+	INV_MPU6050_FILTER_256HZ_NOLPF2 = 0,
+	INV_MPU6050_FILTER_188HZ,
+	INV_MPU6050_FILTER_98HZ,
+	INV_MPU6050_FILTER_42HZ,
+	INV_MPU6050_FILTER_20HZ,
+	INV_MPU6050_FILTER_10HZ,
+	INV_MPU6050_FILTER_5HZ,
+	INV_MPU6050_FILTER_2100HZ_NOLPF,
+	NUM_MPU6050_FILTER
+};
+
+/* IIO attribute address */
+enum INV_MPU6050_IIO_ATTR_ADDR {
+	ATTR_GYRO_MATRIX,
+	ATTR_ACCL_MATRIX,
+};
+
+enum inv_mpu6050_accl_fs_e {
+	INV_MPU6050_FS_02G = 0,
+	INV_MPU6050_FS_04G,
+	INV_MPU6050_FS_08G,
+	INV_MPU6050_FS_16G,
+	NUM_ACCL_FSR
+};
+
+enum inv_mpu6050_fsr_e {
+	INV_MPU6050_FSR_250DPS = 0,
+	INV_MPU6050_FSR_500DPS,
+	INV_MPU6050_FSR_1000DPS,
+	INV_MPU6050_FSR_2000DPS,
+	NUM_MPU6050_FSR
+};
+
+enum inv_mpu6050_clock_sel_e {
+	INV_CLK_INTERNAL = 0,
+	INV_CLK_PLL,
+	NUM_CLK
+};
+
+irqreturn_t inv_mpu6050_irq_handler(int irq, void *p);
+irqreturn_t inv_mpu6050_read_fifo(int irq, void *p);
+int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev);
+void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st);
+int inv_reset_fifo(struct iio_dev *indio_dev);
+int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask);
+int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val);
+int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
new file mode 100644
index 0000000..7da0832
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -0,0 +1,195 @@
+/*
+* Copyright (C) 2012 Invensense, 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.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+#include <linux/jiffies.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kfifo.h>
+#include <linux/poll.h>
+#include "inv_mpu_iio.h"
+
+int inv_reset_fifo(struct iio_dev *indio_dev)
+{
+	int result;
+	u8 d;
+	struct inv_mpu6050_state  *st = iio_priv(indio_dev);
+
+	/* disable interrupt */
+	result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0);
+	if (result) {
+		dev_err(&st->client->dev, "int_enable failed %d\n", result);
+		return result;
+	}
+	/* disable the sensor output to FIFO */
+	result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0);
+	if (result)
+		goto reset_fifo_fail;
+	/* disable fifo reading */
+	result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0);
+	if (result)
+		goto reset_fifo_fail;
+
+	/* reset FIFO*/
+	result = inv_mpu6050_write_reg(st, st->reg->user_ctrl,
+					INV_MPU6050_BIT_FIFO_RST);
+	if (result)
+		goto reset_fifo_fail;
+	/* enable interrupt */
+	if (st->chip_config.accl_fifo_enable ||
+	    st->chip_config.gyro_fifo_enable) {
+		result = inv_mpu6050_write_reg(st, st->reg->int_enable,
+					INV_MPU6050_BIT_DATA_RDY_EN);
+		if (result)
+			return result;
+	}
+	/* enable FIFO reading and I2C master interface*/
+	result = inv_mpu6050_write_reg(st, st->reg->user_ctrl,
+					INV_MPU6050_BIT_FIFO_EN);
+	if (result)
+		goto reset_fifo_fail;
+	/* enable sensor output to FIFO */
+	d = 0;
+	if (st->chip_config.gyro_fifo_enable)
+		d |= INV_MPU6050_BITS_GYRO_OUT;
+	if (st->chip_config.accl_fifo_enable)
+		d |= INV_MPU6050_BIT_ACCEL_OUT;
+	result = inv_mpu6050_write_reg(st, st->reg->fifo_en, d);
+	if (result)
+		goto reset_fifo_fail;
+
+	return 0;
+
+reset_fifo_fail:
+	dev_err(&st->client->dev, "reset fifo failed %d\n", result);
+	result = inv_mpu6050_write_reg(st, st->reg->int_enable,
+					INV_MPU6050_BIT_DATA_RDY_EN);
+
+	return result;
+}
+
+static void inv_clear_kfifo(struct inv_mpu6050_state *st)
+{
+	unsigned long flags;
+
+	/* take the spin lock sem to avoid interrupt kick in */
+	spin_lock_irqsave(&st->time_stamp_lock, flags);
+	kfifo_reset(&st->timestamps);
+	spin_unlock_irqrestore(&st->time_stamp_lock, flags);
+}
+
+/**
+ * inv_mpu6050_irq_handler() - Cache a timestamp at each data ready interrupt.
+ */
+irqreturn_t inv_mpu6050_irq_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct inv_mpu6050_state *st = iio_priv(indio_dev);
+	s64 timestamp;
+
+	timestamp = iio_get_time_ns();
+	kfifo_in_spinlocked(&st->timestamps, &timestamp, 1,
+				&st->time_stamp_lock);
+
+	return IRQ_WAKE_THREAD;
+}
+
+/**
+ * inv_mpu6050_read_fifo() - Transfer data from hardware FIFO to KFIFO.
+ */
+irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct inv_mpu6050_state *st = iio_priv(indio_dev);
+	size_t bytes_per_datum;
+	int result;
+	u8 data[INV_MPU6050_OUTPUT_DATA_SIZE];
+	u16 fifo_count;
+	s64 timestamp;
+	u64 *tmp;
+
+	mutex_lock(&indio_dev->mlock);
+	if (!(st->chip_config.accl_fifo_enable |
+		st->chip_config.gyro_fifo_enable))
+		goto end_session;
+	bytes_per_datum = 0;
+	if (st->chip_config.accl_fifo_enable)
+		bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
+
+	if (st->chip_config.gyro_fifo_enable)
+		bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR;
+
+	/*
+	 * read fifo_count register to know how many bytes inside FIFO
+	 * right now
+	 */
+	result = i2c_smbus_read_i2c_block_data(st->client,
+				       st->reg->fifo_count_h,
+				       INV_MPU6050_FIFO_COUNT_BYTE, data);
+	if (result != INV_MPU6050_FIFO_COUNT_BYTE)
+		goto end_session;
+	fifo_count = be16_to_cpup((__be16 *)(&data[0]));
+	if (fifo_count < bytes_per_datum)
+		goto end_session;
+	/* fifo count can't be odd number, if it is odd, reset fifo*/
+	if (fifo_count & 1)
+		goto flush_fifo;
+	if (fifo_count >  INV_MPU6050_FIFO_THRESHOLD)
+		goto flush_fifo;
+	/* Timestamp mismatch. */
+	if (kfifo_len(&st->timestamps) >
+		fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR)
+			goto flush_fifo;
+	while (fifo_count >= bytes_per_datum) {
+		result = i2c_smbus_read_i2c_block_data(st->client,
+						       st->reg->fifo_r_w,
+						       bytes_per_datum, data);
+		if (result != bytes_per_datum)
+			goto flush_fifo;
+
+		result = kfifo_out(&st->timestamps, &timestamp, 1);
+		/* when there is no timestamp, put timestamp as 0 */
+		if (0 == result)
+			timestamp = 0;
+
+		tmp = (u64 *)data;
+		tmp[DIV_ROUND_UP(bytes_per_datum, 8)] = timestamp;
+		result = iio_push_to_buffers(indio_dev, data);
+		if (result)
+			goto flush_fifo;
+		fifo_count -= bytes_per_datum;
+	}
+
+end_session:
+	mutex_unlock(&indio_dev->mlock);
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+
+flush_fifo:
+	/* Flush HW and SW FIFOs. */
+	inv_reset_fifo(indio_dev);
+	inv_clear_kfifo(st);
+	mutex_unlock(&indio_dev->mlock);
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
new file mode 100644
index 0000000..e1d0869
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -0,0 +1,155 @@
+/*
+* Copyright (C) 2012 Invensense, 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.
+*/
+
+#include "inv_mpu_iio.h"
+
+static void inv_scan_query(struct iio_dev *indio_dev)
+{
+	struct inv_mpu6050_state  *st = iio_priv(indio_dev);
+
+	st->chip_config.gyro_fifo_enable =
+		test_bit(INV_MPU6050_SCAN_GYRO_X,
+			indio_dev->active_scan_mask) ||
+			test_bit(INV_MPU6050_SCAN_GYRO_Y,
+			indio_dev->active_scan_mask) ||
+			test_bit(INV_MPU6050_SCAN_GYRO_Z,
+			indio_dev->active_scan_mask);
+
+	st->chip_config.accl_fifo_enable =
+		test_bit(INV_MPU6050_SCAN_ACCL_X,
+			indio_dev->active_scan_mask) ||
+			test_bit(INV_MPU6050_SCAN_ACCL_Y,
+			indio_dev->active_scan_mask) ||
+			test_bit(INV_MPU6050_SCAN_ACCL_Z,
+			indio_dev->active_scan_mask);
+}
+
+/**
+ *  inv_mpu6050_set_enable() - enable chip functions.
+ *  @indio_dev:	Device driver instance.
+ *  @enable: enable/disable
+ */
+static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
+{
+	struct inv_mpu6050_state *st = iio_priv(indio_dev);
+	int result;
+
+	if (enable) {
+		result = inv_mpu6050_set_power_itg(st, true);
+		if (result)
+			return result;
+		inv_scan_query(indio_dev);
+		if (st->chip_config.gyro_fifo_enable) {
+			result = inv_mpu6050_switch_engine(st, true,
+					INV_MPU6050_BIT_PWR_GYRO_STBY);
+			if (result)
+				return result;
+		}
+		if (st->chip_config.accl_fifo_enable) {
+			result = inv_mpu6050_switch_engine(st, true,
+					INV_MPU6050_BIT_PWR_ACCL_STBY);
+			if (result)
+				return result;
+		}
+		result = inv_reset_fifo(indio_dev);
+		if (result)
+			return result;
+	} else {
+		result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0);
+		if (result)
+			return result;
+
+		result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0);
+		if (result)
+			return result;
+
+		result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0);
+		if (result)
+			return result;
+
+		result = inv_mpu6050_switch_engine(st, false,
+					INV_MPU6050_BIT_PWR_GYRO_STBY);
+		if (result)
+			return result;
+
+		result = inv_mpu6050_switch_engine(st, false,
+					INV_MPU6050_BIT_PWR_ACCL_STBY);
+		if (result)
+			return result;
+		result = inv_mpu6050_set_power_itg(st, false);
+		if (result)
+			return result;
+	}
+	st->chip_config.enable = enable;
+
+	return 0;
+}
+
+/**
+ * inv_mpu_data_rdy_trigger_set_state() - set data ready interrupt state
+ * @trig: Trigger instance
+ * @state: Desired trigger state
+ */
+static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig,
+						bool state)
+{
+	return inv_mpu6050_set_enable(trig->private_data, state);
+}
+
+static const struct iio_trigger_ops inv_mpu_trigger_ops = {
+	.owner = THIS_MODULE,
+	.set_trigger_state = &inv_mpu_data_rdy_trigger_set_state,
+};
+
+int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
+{
+	int ret;
+	struct inv_mpu6050_state *st = iio_priv(indio_dev);
+
+	st->trig = iio_trigger_alloc("%s-dev%d",
+					indio_dev->name,
+					indio_dev->id);
+	if (st->trig == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	ret = request_irq(st->client->irq, &iio_trigger_generic_data_rdy_poll,
+				IRQF_TRIGGER_RISING,
+				"inv_mpu",
+				st->trig);
+	if (ret)
+		goto error_free_trig;
+	st->trig->dev.parent = &st->client->dev;
+	st->trig->private_data = indio_dev;
+	st->trig->ops = &inv_mpu_trigger_ops;
+	ret = iio_trigger_register(st->trig);
+	if (ret)
+		goto error_free_irq;
+	indio_dev->trig = st->trig;
+
+	return 0;
+
+error_free_irq:
+	free_irq(st->client->irq, st->trig);
+error_free_trig:
+	iio_trigger_free(st->trig);
+error_ret:
+	return ret;
+}
+
+void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st)
+{
+	iio_trigger_unregister(st->trig);
+	free_irq(st->client->irq, st->trig);
+	iio_trigger_free(st->trig);
+}
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index ff11d68..cd29be5 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -14,4 +14,34 @@ config HID_SENSOR_MAGNETOMETER_3D
 	  Say yes here to build support for the HID SENSOR
 	  Magnetometer 3D.
 
+config IIO_ST_MAGN_3AXIS
+	tristate "STMicroelectronics magnetometers 3-Axis Driver"
+	depends on (I2C || SPI_MASTER) && SYSFS
+	select IIO_ST_SENSORS_CORE
+	select IIO_ST_MAGN_I2C_3AXIS if (I2C)
+	select IIO_ST_MAGN_SPI_3AXIS if (SPI_MASTER)
+	select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
+	select IIO_ST_MAGN_BUFFER if (IIO_TRIGGERED_BUFFER)
+	help
+	  Say yes here to build support for STMicroelectronics magnetometers:
+	  LSM303DLHC, LSM303DLM, LIS3MDL.
+
+	  This driver can also be built as a module. If so, will be created
+	  these modules:
+	  - st_magn (core functions for the driver [it is mandatory]);
+	  - st_magn_i2c (necessary for the I2C devices [optional*]);
+	  - st_magn_spi (necessary for the SPI devices [optional*]);
+
+	  (*) one of these is necessary to do something.
+
+config IIO_ST_MAGN_I2C_3AXIS
+	tristate
+	depends on IIO_ST_MAGN_3AXIS
+	depends on IIO_ST_SENSORS_I2C
+
+config IIO_ST_MAGN_SPI_3AXIS
+	tristate
+	depends on IIO_ST_MAGN_3AXIS
+	depends on IIO_ST_SENSORS_SPI
+
 endmenu
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
index 60dc4f2..e786728 100644
--- a/drivers/iio/magnetometer/Makefile
+++ b/drivers/iio/magnetometer/Makefile
@@ -3,3 +3,10 @@
 #
 
 obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
+
+obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o
+st_magn-y := st_magn_core.o
+st_magn-$(CONFIG_IIO_BUFFER) += st_magn_buffer.o
+
+obj-$(CONFIG_IIO_ST_MAGN_I2C_3AXIS) += st_magn_i2c.o
+obj-$(CONFIG_IIO_ST_MAGN_SPI_3AXIS) += st_magn_spi.o
diff --git a/drivers/iio/magnetometer/st_magn.h b/drivers/iio/magnetometer/st_magn.h
new file mode 100644
index 0000000..7e81d00
--- /dev/null
+++ b/drivers/iio/magnetometer/st_magn.h
@@ -0,0 +1,45 @@
+/*
+ * STMicroelectronics magnetometers driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ * v. 1.0.0
+ * Licensed under the GPL-2.
+ */
+
+#ifndef ST_MAGN_H
+#define ST_MAGN_H
+
+#include <linux/types.h>
+#include <linux/iio/common/st_sensors.h>
+
+#define LSM303DLHC_MAGN_DEV_NAME	"lsm303dlhc_magn"
+#define LSM303DLM_MAGN_DEV_NAME		"lsm303dlm_magn"
+#define LIS3MDL_MAGN_DEV_NAME		"lis3mdl"
+
+int st_magn_common_probe(struct iio_dev *indio_dev);
+void st_magn_common_remove(struct iio_dev *indio_dev);
+
+#ifdef CONFIG_IIO_BUFFER
+int st_magn_allocate_ring(struct iio_dev *indio_dev);
+void st_magn_deallocate_ring(struct iio_dev *indio_dev);
+#else /* CONFIG_IIO_BUFFER */
+static inline int st_magn_probe_trigger(struct iio_dev *indio_dev, int irq)
+{
+	return 0;
+}
+static inline void st_magn_remove_trigger(struct iio_dev *indio_dev, int irq)
+{
+	return;
+}
+static inline int st_magn_allocate_ring(struct iio_dev *indio_dev)
+{
+	return 0;
+}
+static inline void st_magn_deallocate_ring(struct iio_dev *indio_dev)
+{
+}
+#endif /* CONFIG_IIO_BUFFER */
+
+#endif /* ST_MAGN_H */
diff --git a/drivers/iio/magnetometer/st_magn_buffer.c b/drivers/iio/magnetometer/st_magn_buffer.c
new file mode 100644
index 0000000..708857b
--- /dev/null
+++ b/drivers/iio/magnetometer/st_magn_buffer.c
@@ -0,0 +1,98 @@
+/*
+ * STMicroelectronics magnetometers driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/delay.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/common/st_sensors.h>
+#include "st_magn.h"
+
+static int st_magn_buffer_preenable(struct iio_dev *indio_dev)
+{
+	int err;
+
+	err = st_sensors_set_enable(indio_dev, true);
+	if (err < 0)
+		goto st_magn_set_enable_error;
+
+	err = iio_sw_buffer_preenable(indio_dev);
+
+st_magn_set_enable_error:
+	return err;
+}
+
+static int st_magn_buffer_postenable(struct iio_dev *indio_dev)
+{
+	int err;
+	struct st_sensor_data *mdata = iio_priv(indio_dev);
+
+	mdata->buffer_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (mdata->buffer_data == NULL) {
+		err = -ENOMEM;
+		goto allocate_memory_error;
+	}
+
+	err = iio_triggered_buffer_postenable(indio_dev);
+	if (err < 0)
+		goto st_magn_buffer_postenable_error;
+
+	return err;
+
+st_magn_buffer_postenable_error:
+	kfree(mdata->buffer_data);
+allocate_memory_error:
+	return err;
+}
+
+static int st_magn_buffer_predisable(struct iio_dev *indio_dev)
+{
+	int err;
+	struct st_sensor_data *mdata = iio_priv(indio_dev);
+
+	err = iio_triggered_buffer_predisable(indio_dev);
+	if (err < 0)
+		goto st_magn_buffer_predisable_error;
+
+	err = st_sensors_set_enable(indio_dev, false);
+
+st_magn_buffer_predisable_error:
+	kfree(mdata->buffer_data);
+	return err;
+}
+
+static const struct iio_buffer_setup_ops st_magn_buffer_setup_ops = {
+	.preenable = &st_magn_buffer_preenable,
+	.postenable = &st_magn_buffer_postenable,
+	.predisable = &st_magn_buffer_predisable,
+};
+
+int st_magn_allocate_ring(struct iio_dev *indio_dev)
+{
+	return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+		&st_sensors_trigger_handler, &st_magn_buffer_setup_ops);
+}
+
+void st_magn_deallocate_ring(struct iio_dev *indio_dev)
+{
+	iio_triggered_buffer_cleanup(indio_dev);
+}
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics magnetometers buffer");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
new file mode 100644
index 0000000..a69fbe1
--- /dev/null
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -0,0 +1,401 @@
+/*
+ * STMicroelectronics magnetometers driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+
+#include <linux/iio/common/st_sensors.h>
+#include "st_magn.h"
+
+/* DEFAULT VALUE FOR SENSORS */
+#define ST_MAGN_DEFAULT_OUT_X_L_ADDR		0X04
+#define ST_MAGN_DEFAULT_OUT_Y_L_ADDR		0X08
+#define ST_MAGN_DEFAULT_OUT_Z_L_ADDR		0X06
+
+/* FULLSCALE */
+#define ST_MAGN_FS_AVL_1300MG			1300
+#define ST_MAGN_FS_AVL_1900MG			1900
+#define ST_MAGN_FS_AVL_2500MG			2500
+#define ST_MAGN_FS_AVL_4000MG			4000
+#define ST_MAGN_FS_AVL_4700MG			4700
+#define ST_MAGN_FS_AVL_5600MG			5600
+#define ST_MAGN_FS_AVL_8000MG			8000
+#define ST_MAGN_FS_AVL_8100MG			8100
+#define ST_MAGN_FS_AVL_10000MG			10000
+
+/* CUSTOM VALUES FOR SENSOR 1 */
+#define ST_MAGN_1_WAI_EXP			0x3c
+#define ST_MAGN_1_ODR_ADDR			0x00
+#define ST_MAGN_1_ODR_MASK			0x1c
+#define ST_MAGN_1_ODR_AVL_1HZ_VAL		0x00
+#define ST_MAGN_1_ODR_AVL_2HZ_VAL		0x01
+#define ST_MAGN_1_ODR_AVL_3HZ_VAL		0x02
+#define ST_MAGN_1_ODR_AVL_8HZ_VAL		0x03
+#define ST_MAGN_1_ODR_AVL_15HZ_VAL		0x04
+#define ST_MAGN_1_ODR_AVL_30HZ_VAL		0x05
+#define ST_MAGN_1_ODR_AVL_75HZ_VAL		0x06
+#define ST_MAGN_1_ODR_AVL_220HZ_VAL		0x07
+#define ST_MAGN_1_PW_ADDR			0x02
+#define ST_MAGN_1_PW_MASK			0x03
+#define ST_MAGN_1_PW_ON				0x00
+#define ST_MAGN_1_PW_OFF			0x03
+#define ST_MAGN_1_FS_ADDR			0x01
+#define ST_MAGN_1_FS_MASK			0xe0
+#define ST_MAGN_1_FS_AVL_1300_VAL		0x01
+#define ST_MAGN_1_FS_AVL_1900_VAL		0x02
+#define ST_MAGN_1_FS_AVL_2500_VAL		0x03
+#define ST_MAGN_1_FS_AVL_4000_VAL		0x04
+#define ST_MAGN_1_FS_AVL_4700_VAL		0x05
+#define ST_MAGN_1_FS_AVL_5600_VAL		0x06
+#define ST_MAGN_1_FS_AVL_8100_VAL		0x07
+#define ST_MAGN_1_FS_AVL_1300_GAIN_XY		1100
+#define ST_MAGN_1_FS_AVL_1900_GAIN_XY		855
+#define ST_MAGN_1_FS_AVL_2500_GAIN_XY		670
+#define ST_MAGN_1_FS_AVL_4000_GAIN_XY		450
+#define ST_MAGN_1_FS_AVL_4700_GAIN_XY		400
+#define ST_MAGN_1_FS_AVL_5600_GAIN_XY		330
+#define ST_MAGN_1_FS_AVL_8100_GAIN_XY		230
+#define ST_MAGN_1_FS_AVL_1300_GAIN_Z		980
+#define ST_MAGN_1_FS_AVL_1900_GAIN_Z		760
+#define ST_MAGN_1_FS_AVL_2500_GAIN_Z		600
+#define ST_MAGN_1_FS_AVL_4000_GAIN_Z		400
+#define ST_MAGN_1_FS_AVL_4700_GAIN_Z		355
+#define ST_MAGN_1_FS_AVL_5600_GAIN_Z		295
+#define ST_MAGN_1_FS_AVL_8100_GAIN_Z		205
+#define ST_MAGN_1_MULTIREAD_BIT			false
+
+/* CUSTOM VALUES FOR SENSOR 2 */
+#define ST_MAGN_2_WAI_EXP			0x3d
+#define ST_MAGN_2_ODR_ADDR			0x20
+#define ST_MAGN_2_ODR_MASK			0x1c
+#define ST_MAGN_2_ODR_AVL_1HZ_VAL		0x00
+#define ST_MAGN_2_ODR_AVL_2HZ_VAL		0x01
+#define ST_MAGN_2_ODR_AVL_3HZ_VAL		0x02
+#define ST_MAGN_2_ODR_AVL_5HZ_VAL		0x03
+#define ST_MAGN_2_ODR_AVL_10HZ_VAL		0x04
+#define ST_MAGN_2_ODR_AVL_20HZ_VAL		0x05
+#define ST_MAGN_2_ODR_AVL_40HZ_VAL		0x06
+#define ST_MAGN_2_ODR_AVL_80HZ_VAL		0x07
+#define ST_MAGN_2_PW_ADDR			0x22
+#define ST_MAGN_2_PW_MASK			0x03
+#define ST_MAGN_2_PW_ON				0x00
+#define ST_MAGN_2_PW_OFF			0x03
+#define ST_MAGN_2_FS_ADDR			0x21
+#define ST_MAGN_2_FS_MASK			0x60
+#define ST_MAGN_2_FS_AVL_4000_VAL		0x00
+#define ST_MAGN_2_FS_AVL_8000_VAL		0x01
+#define ST_MAGN_2_FS_AVL_10000_VAL		0x02
+#define ST_MAGN_2_FS_AVL_4000_GAIN		430
+#define ST_MAGN_2_FS_AVL_8000_GAIN		230
+#define ST_MAGN_2_FS_AVL_10000_GAIN		230
+#define ST_MAGN_2_MULTIREAD_BIT			false
+#define ST_MAGN_2_OUT_X_L_ADDR			0x28
+#define ST_MAGN_2_OUT_Y_L_ADDR			0x2a
+#define ST_MAGN_2_OUT_Z_L_ADDR			0x2c
+
+static const struct iio_chan_spec st_magn_16bit_channels[] = {
+	ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_X, IIO_MOD_X, IIO_LE,
+		ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_DEFAULT_OUT_X_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_Y, IIO_MOD_Y, IIO_LE,
+		ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_DEFAULT_OUT_Y_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_Z, IIO_MOD_Z, IIO_LE,
+		ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_DEFAULT_OUT_Z_L_ADDR),
+	IIO_CHAN_SOFT_TIMESTAMP(3)
+};
+
+static const struct iio_chan_spec st_magn_2_16bit_channels[] = {
+	ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_X, IIO_MOD_X, IIO_LE,
+		ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_2_OUT_X_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_Y, IIO_MOD_Y, IIO_LE,
+		ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_2_OUT_Y_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_MAGN, ST_SENSORS_SCAN_Z, IIO_MOD_Z, IIO_LE,
+		ST_SENSORS_DEFAULT_16_REALBITS, ST_MAGN_2_OUT_Z_L_ADDR),
+	IIO_CHAN_SOFT_TIMESTAMP(3)
+};
+
+static const struct st_sensors st_magn_sensors[] = {
+	{
+		.wai = ST_MAGN_1_WAI_EXP,
+		.sensors_supported = {
+			[0] = LSM303DLHC_MAGN_DEV_NAME,
+			[1] = LSM303DLM_MAGN_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_magn_16bit_channels,
+		.odr = {
+			.addr = ST_MAGN_1_ODR_ADDR,
+			.mask = ST_MAGN_1_ODR_MASK,
+			.odr_avl = {
+				{ 1, ST_MAGN_1_ODR_AVL_1HZ_VAL, },
+				{ 2, ST_MAGN_1_ODR_AVL_2HZ_VAL, },
+				{ 3, ST_MAGN_1_ODR_AVL_3HZ_VAL, },
+				{ 8, ST_MAGN_1_ODR_AVL_8HZ_VAL, },
+				{ 15, ST_MAGN_1_ODR_AVL_15HZ_VAL, },
+				{ 30, ST_MAGN_1_ODR_AVL_30HZ_VAL, },
+				{ 75, ST_MAGN_1_ODR_AVL_75HZ_VAL, },
+				{ 220, ST_MAGN_1_ODR_AVL_220HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_MAGN_1_PW_ADDR,
+			.mask = ST_MAGN_1_PW_MASK,
+			.value_on = ST_MAGN_1_PW_ON,
+			.value_off = ST_MAGN_1_PW_OFF,
+		},
+		.fs = {
+			.addr = ST_MAGN_1_FS_ADDR,
+			.mask = ST_MAGN_1_FS_MASK,
+			.fs_avl = {
+				[0] = {
+					.num = ST_MAGN_FS_AVL_1300MG,
+					.value = ST_MAGN_1_FS_AVL_1300_VAL,
+					.gain = ST_MAGN_1_FS_AVL_1300_GAIN_XY,
+					.gain2 = ST_MAGN_1_FS_AVL_1300_GAIN_Z,
+				},
+				[1] = {
+					.num = ST_MAGN_FS_AVL_1900MG,
+					.value = ST_MAGN_1_FS_AVL_1900_VAL,
+					.gain = ST_MAGN_1_FS_AVL_1900_GAIN_XY,
+					.gain2 = ST_MAGN_1_FS_AVL_1900_GAIN_Z,
+				},
+				[2] = {
+					.num = ST_MAGN_FS_AVL_2500MG,
+					.value = ST_MAGN_1_FS_AVL_2500_VAL,
+					.gain = ST_MAGN_1_FS_AVL_2500_GAIN_XY,
+					.gain2 = ST_MAGN_1_FS_AVL_2500_GAIN_Z,
+				},
+				[3] = {
+					.num = ST_MAGN_FS_AVL_4000MG,
+					.value = ST_MAGN_1_FS_AVL_4000_VAL,
+					.gain = ST_MAGN_1_FS_AVL_4000_GAIN_XY,
+					.gain2 = ST_MAGN_1_FS_AVL_4000_GAIN_Z,
+				},
+				[4] = {
+					.num = ST_MAGN_FS_AVL_4700MG,
+					.value = ST_MAGN_1_FS_AVL_4700_VAL,
+					.gain = ST_MAGN_1_FS_AVL_4700_GAIN_XY,
+					.gain2 = ST_MAGN_1_FS_AVL_4700_GAIN_Z,
+				},
+				[5] = {
+					.num = ST_MAGN_FS_AVL_5600MG,
+					.value = ST_MAGN_1_FS_AVL_5600_VAL,
+					.gain = ST_MAGN_1_FS_AVL_5600_GAIN_XY,
+					.gain2 = ST_MAGN_1_FS_AVL_5600_GAIN_Z,
+				},
+				[6] = {
+					.num = ST_MAGN_FS_AVL_8100MG,
+					.value = ST_MAGN_1_FS_AVL_8100_VAL,
+					.gain = ST_MAGN_1_FS_AVL_8100_GAIN_XY,
+					.gain2 = ST_MAGN_1_FS_AVL_8100_GAIN_Z,
+				},
+			},
+		},
+		.multi_read_bit = ST_MAGN_1_MULTIREAD_BIT,
+		.bootime = 2,
+	},
+	{
+		.wai = ST_MAGN_2_WAI_EXP,
+		.sensors_supported = {
+			[0] = LIS3MDL_MAGN_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_magn_2_16bit_channels,
+		.odr = {
+			.addr = ST_MAGN_2_ODR_ADDR,
+			.mask = ST_MAGN_2_ODR_MASK,
+			.odr_avl = {
+				{ 1, ST_MAGN_2_ODR_AVL_1HZ_VAL, },
+				{ 2, ST_MAGN_2_ODR_AVL_2HZ_VAL, },
+				{ 3, ST_MAGN_2_ODR_AVL_3HZ_VAL, },
+				{ 5, ST_MAGN_2_ODR_AVL_5HZ_VAL, },
+				{ 10, ST_MAGN_2_ODR_AVL_10HZ_VAL, },
+				{ 20, ST_MAGN_2_ODR_AVL_20HZ_VAL, },
+				{ 40, ST_MAGN_2_ODR_AVL_40HZ_VAL, },
+				{ 80, ST_MAGN_2_ODR_AVL_80HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_MAGN_2_PW_ADDR,
+			.mask = ST_MAGN_2_PW_MASK,
+			.value_on = ST_MAGN_2_PW_ON,
+			.value_off = ST_MAGN_2_PW_OFF,
+		},
+		.fs = {
+			.addr = ST_MAGN_2_FS_ADDR,
+			.mask = ST_MAGN_2_FS_MASK,
+			.fs_avl = {
+				[0] = {
+					.num = ST_MAGN_FS_AVL_4000MG,
+					.value = ST_MAGN_2_FS_AVL_4000_VAL,
+					.gain = ST_MAGN_2_FS_AVL_4000_GAIN,
+				},
+				[1] = {
+					.num = ST_MAGN_FS_AVL_8000MG,
+					.value = ST_MAGN_2_FS_AVL_8000_VAL,
+					.gain = ST_MAGN_2_FS_AVL_8000_GAIN,
+				},
+				[2] = {
+					.num = ST_MAGN_FS_AVL_10000MG,
+					.value = ST_MAGN_2_FS_AVL_10000_VAL,
+					.gain = ST_MAGN_2_FS_AVL_10000_GAIN,
+				},
+			},
+		},
+		.multi_read_bit = ST_MAGN_2_MULTIREAD_BIT,
+		.bootime = 2,
+	},
+};
+
+static int st_magn_read_raw(struct iio_dev *indio_dev,
+			struct iio_chan_spec const *ch, int *val,
+							int *val2, long mask)
+{
+	int err;
+	struct st_sensor_data *mdata = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		err = st_sensors_read_info_raw(indio_dev, ch, val);
+		if (err < 0)
+			goto read_error;
+
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		if ((ch->scan_index == ST_SENSORS_SCAN_Z) &&
+					(mdata->current_fullscale->gain2 != 0))
+			*val2 = mdata->current_fullscale->gain2;
+		else
+			*val2 = mdata->current_fullscale->gain;
+		return IIO_VAL_INT_PLUS_MICRO;
+	default:
+		return -EINVAL;
+	}
+
+read_error:
+	return err;
+}
+
+static int st_magn_write_raw(struct iio_dev *indio_dev,
+		struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+	int err;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
+static ST_SENSOR_DEV_ATTR_SAMP_FREQ();
+static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
+static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_magn_scale_available);
+
+static struct attribute *st_magn_attributes[] = {
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+	&iio_dev_attr_in_magn_scale_available.dev_attr.attr,
+	&iio_dev_attr_sampling_frequency.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group st_magn_attribute_group = {
+	.attrs = st_magn_attributes,
+};
+
+static const struct iio_info magn_info = {
+	.driver_module = THIS_MODULE,
+	.attrs = &st_magn_attribute_group,
+	.read_raw = &st_magn_read_raw,
+	.write_raw = &st_magn_write_raw,
+};
+
+int st_magn_common_probe(struct iio_dev *indio_dev)
+{
+	int err;
+	struct st_sensor_data *mdata = iio_priv(indio_dev);
+
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->info = &magn_info;
+
+	err = st_sensors_check_device_support(indio_dev,
+				ARRAY_SIZE(st_magn_sensors), st_magn_sensors);
+	if (err < 0)
+		goto st_magn_common_probe_error;
+
+	mdata->multiread_bit = mdata->sensor->multi_read_bit;
+	indio_dev->channels = mdata->sensor->ch;
+	indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
+
+	mdata->current_fullscale = (struct st_sensor_fullscale_avl *)
+						&mdata->sensor->fs.fs_avl[0];
+	mdata->odr = mdata->sensor->odr.odr_avl[0].hz;
+
+	err = st_sensors_init_sensor(indio_dev);
+	if (err < 0)
+		goto st_magn_common_probe_error;
+
+	if (mdata->get_irq_data_ready(indio_dev) > 0) {
+		err = st_magn_allocate_ring(indio_dev);
+		if (err < 0)
+			goto st_magn_common_probe_error;
+		err = st_sensors_allocate_trigger(indio_dev, NULL);
+		if (err < 0)
+			goto st_magn_probe_trigger_error;
+	}
+
+	err = iio_device_register(indio_dev);
+	if (err)
+		goto st_magn_device_register_error;
+
+	return err;
+
+st_magn_device_register_error:
+	if (mdata->get_irq_data_ready(indio_dev) > 0)
+		st_sensors_deallocate_trigger(indio_dev);
+st_magn_probe_trigger_error:
+	if (mdata->get_irq_data_ready(indio_dev) > 0)
+		st_magn_deallocate_ring(indio_dev);
+st_magn_common_probe_error:
+	return err;
+}
+EXPORT_SYMBOL(st_magn_common_probe);
+
+void st_magn_common_remove(struct iio_dev *indio_dev)
+{
+	struct st_sensor_data *mdata = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	if (mdata->get_irq_data_ready(indio_dev) > 0) {
+		st_sensors_deallocate_trigger(indio_dev);
+		st_magn_deallocate_ring(indio_dev);
+	}
+	iio_device_free(indio_dev);
+}
+EXPORT_SYMBOL(st_magn_common_remove);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics magnetometers driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c
new file mode 100644
index 0000000..710b256a5
--- /dev/null
+++ b/drivers/iio/magnetometer/st_magn_i2c.c
@@ -0,0 +1,81 @@
+/*
+ * STMicroelectronics magnetometers driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+
+#include <linux/iio/common/st_sensors.h>
+#include <linux/iio/common/st_sensors_i2c.h>
+#include "st_magn.h"
+
+static int st_magn_i2c_probe(struct i2c_client *client,
+						const struct i2c_device_id *id)
+{
+	struct iio_dev *indio_dev;
+	struct st_sensor_data *mdata;
+	int err;
+
+	indio_dev = iio_device_alloc(sizeof(*mdata));
+	if (indio_dev == NULL) {
+		err = -ENOMEM;
+		goto iio_device_alloc_error;
+	}
+
+	mdata = iio_priv(indio_dev);
+	mdata->dev = &client->dev;
+
+	st_sensors_i2c_configure(indio_dev, client, mdata);
+
+	err = st_magn_common_probe(indio_dev);
+	if (err < 0)
+		goto st_magn_common_probe_error;
+
+	return 0;
+
+st_magn_common_probe_error:
+	iio_device_free(indio_dev);
+iio_device_alloc_error:
+	return err;
+}
+
+static int st_magn_i2c_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	st_magn_common_remove(indio_dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id st_magn_id_table[] = {
+	{ LSM303DLHC_MAGN_DEV_NAME },
+	{ LSM303DLM_MAGN_DEV_NAME },
+	{ LIS3MDL_MAGN_DEV_NAME },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, st_magn_id_table);
+
+static struct i2c_driver st_magn_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "st-magn-i2c",
+	},
+	.probe = st_magn_i2c_probe,
+	.remove = st_magn_i2c_remove,
+	.id_table = st_magn_id_table,
+};
+module_i2c_driver(st_magn_driver);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics magnetometers i2c driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c
new file mode 100644
index 0000000..94547e7
--- /dev/null
+++ b/drivers/iio/magnetometer/st_magn_spi.c
@@ -0,0 +1,80 @@
+/*
+ * STMicroelectronics magnetometers driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+
+#include <linux/iio/common/st_sensors.h>
+#include <linux/iio/common/st_sensors_spi.h>
+#include "st_magn.h"
+
+static int st_magn_spi_probe(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev;
+	struct st_sensor_data *mdata;
+	int err;
+
+	indio_dev = iio_device_alloc(sizeof(*mdata));
+	if (indio_dev == NULL) {
+		err = -ENOMEM;
+		goto iio_device_alloc_error;
+	}
+
+	mdata = iio_priv(indio_dev);
+	mdata->dev = &spi->dev;
+
+	st_sensors_spi_configure(indio_dev, spi, mdata);
+
+	err = st_magn_common_probe(indio_dev);
+	if (err < 0)
+		goto st_magn_common_probe_error;
+
+	return 0;
+
+st_magn_common_probe_error:
+	iio_device_free(indio_dev);
+iio_device_alloc_error:
+	return err;
+}
+
+static int st_magn_spi_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	st_magn_common_remove(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id st_magn_id_table[] = {
+	{ LSM303DLHC_MAGN_DEV_NAME },
+	{ LSM303DLM_MAGN_DEV_NAME },
+	{ LIS3MDL_MAGN_DEV_NAME },
+	{},
+};
+MODULE_DEVICE_TABLE(spi, st_magn_id_table);
+
+static struct spi_driver st_magn_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "st-magn-spi",
+	},
+	.probe = st_magn_spi_probe,
+	.remove = st_magn_spi_remove,
+	.id_table = st_magn_id_table,
+};
+module_spi_driver(st_magn_driver);
+
+MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics magnetometers spi driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index b29ca65..97d7e05 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -29,6 +29,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
 #include <linux/spinlock.h>
+#include <linux/pinctrl/consumer.h>
 
 struct gpio_button_data {
 	const struct gpio_keys_button *button;
@@ -692,6 +693,7 @@ static int gpio_keys_probe(struct platform_device *pdev)
 	struct input_dev *input;
 	int i, error;
 	int wakeup = 0;
+	struct pinctrl *pinctrl;
 
 	if (!pdata) {
 		pdata = gpio_keys_get_devtree_pdata(dev);
@@ -757,6 +759,18 @@ static int gpio_keys_probe(struct platform_device *pdev)
 		goto fail3;
 	}
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev, "unable to select pin group\n");
+
+	/* 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;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index d04f810..ca94635 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -13,6 +13,9 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/async.h>
+#include <linux/completion.h>
+#include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/firmware.h>
 #include <linux/i2c.h>
@@ -20,6 +23,12 @@
 #include <linux/input/mt.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#if defined(CONFIG_ACPI_BUTTON)
+#include <acpi/button.h>
+#endif
+
 
 /* Version */
 #define MXT_VER_20		20
@@ -29,12 +38,22 @@
 /* Slave addresses */
 #define MXT_APP_LOW		0x4a
 #define MXT_APP_HIGH		0x4b
-#define MXT_BOOT_LOW		0x24
+/*
+ * MXT_BOOT_LOW disagrees with Atmel documentation, but has been
+ * updated to support new touch hardware that pairs 0x26 boot with 0x4a app.
+ */
+#define MXT_BOOT_LOW		0x26
 #define MXT_BOOT_HIGH		0x25
 
 /* Firmware */
 #define MXT_FW_NAME		"maxtouch.fw"
 
+/* Config file */
+#define MXT_CONFIG_NAME		"maxtouch.cfg"
+
+/* Configuration Data */
+#define MXT_CONFIG_VERSION	"OBP_RAW V1"
+
 /* Registers */
 #define MXT_INFO		0x00
 #define MXT_FAMILY_ID		0x00
@@ -68,6 +87,11 @@
 #define MXT_PROCI_TOUCHSUPPRESSION_T42	42
 #define MXT_PROCI_STYLUS_T47		47
 #define MXT_PROCG_NOISESUPPRESSION_T48	48
+#define MXT_PROCI_ADAPTIVETHRESHOLD_T55 55
+#define MXT_PROCI_SHIELDLESS_T56	56
+#define MXT_PROCI_EXTRATOUCHSCREENDATA_T57	57
+#define MXT_PROCG_NOISESUPPRESSION_T62	62
+#define MXT_PROCI_LENSBENDING_T65	65
 #define MXT_SPT_COMMSCONFIG_T18		18
 #define MXT_SPT_GPIOPWM_T19		19
 #define MXT_SPT_SELFTEST_T25		25
@@ -76,6 +100,7 @@
 #define MXT_SPT_DIGITIZER_T43		43
 #define MXT_SPT_MESSAGECOUNT_T44	44
 #define MXT_SPT_CTECONFIG_T46		46
+#define MXT_SPT_TIMER_T61		61
 
 /* MXT_GEN_COMMAND_T6 field */
 #define MXT_COMMAND_RESET	0
@@ -84,6 +109,13 @@
 #define MXT_COMMAND_REPORTALL	3
 #define MXT_COMMAND_DIAGNOSTIC	5
 
+#define MXT_T6_CMD_PAGE_UP		0x01
+#define MXT_T6_CMD_PAGE_DOWN		0x02
+#define MXT_T6_CMD_DELTAS		0x10
+#define MXT_T6_CMD_REFS			0x11
+#define MXT_T6_CMD_DEVICE_ID		0x80
+#define MXT_T6_CMD_TOUCH_THRESH		0xF4
+
 /* MXT_GEN_POWER_T7 field */
 #define MXT_POWER_IDLEACQINT	0
 #define MXT_POWER_ACTVACQINT	1
@@ -128,6 +160,22 @@
 #define MXT_TOUCH_YEDGEDIST	29
 #define MXT_TOUCH_JUMPLIMIT	30
 
+/* MXT_TOUCH_CTRL bits */
+#define MXT_TOUCH_CTRL_ENABLE	(1 << 0)
+#define MXT_TOUCH_CTRL_RPTEN	(1 << 1)
+#define MXT_TOUCH_CTRL_DISAMP	(1 << 2)
+#define MXT_TOUCH_CTRL_DISVECT	(1 << 3)
+#define MXT_TOUCH_CTRL_DISMOVE	(1 << 4)
+#define MXT_TOUCH_CTRL_DISREL	(1 << 5)
+#define MXT_TOUCH_CTRL_DISPRESS	(1 << 6)
+#define MXT_TOUCH_CTRL_SCANEN	(1 << 7)
+#define MXT_TOUCH_CTRL_OPERATIONAL	(MXT_TOUCH_CTRL_ENABLE | \
+					 MXT_TOUCH_CTRL_SCANEN | \
+					 MXT_TOUCH_CTRL_RPTEN)
+#define MXT_TOUCH_CTRL_SCANNING		(MXT_TOUCH_CTRL_ENABLE | \
+					 MXT_TOUCH_CTRL_SCANEN)
+#define MXT_TOUCH_CTRL_OFF		0x0
+
 /* MXT_PROCI_GRIPFACE_T20 field */
 #define MXT_GRIPFACE_CTRL	0
 #define MXT_GRIPFACE_XLOGRIP	1
@@ -176,10 +224,20 @@
 /* Define for MXT_GEN_COMMAND_T6 */
 #define MXT_BOOT_VALUE		0xa5
 #define MXT_BACKUP_VALUE	0x55
-#define MXT_BACKUP_TIME		25	/* msec */
-#define MXT_RESET_TIME		65	/* msec */
+#define MXT_BACKUP_TIME		270	/* msec */
+#define MXT_RESET_TIME		350	/* msec */
+#define MXT_CAL_TIME		25	/* msec */
+
+#define MXT_FWRESET_TIME	500	/* msec */
 
-#define MXT_FWRESET_TIME	175	/* msec */
+/* Default value for acquisition interval when in suspend mode*/
+#define MXT_SUSPEND_ACQINT_VALUE 32      /* msec */
+
+/* MXT_SPT_GPIOPWM_T19 field */
+#define MXT_GPIO0_MASK		0x04
+#define MXT_GPIO1_MASK		0x08
+#define MXT_GPIO2_MASK		0x10
+#define MXT_GPIO3_MASK		0x20
 
 /* Command to unlock bootloader */
 #define MXT_UNLOCK_CMD_MSB	0xaa
@@ -212,6 +270,24 @@
 /* Touchscreen absolute values */
 #define MXT_MAX_AREA		0xff
 
+#define MXT_MAX_FINGER		10
+
+/* For CMT (must match XRANGE/YRANGE as defined in board config */
+#define MXT_PIXELS_PER_MM	20
+
+struct mxt_cfg_file_hdr {
+	bool valid;
+	u32 info_crc;
+	u32 cfg_crc;
+};
+
+struct mxt_cfg_file_line {
+	struct list_head list;
+	u16 addr;
+	u8 size;
+	u8 *content;
+};
+
 struct mxt_info {
 	u8 family_id;
 	u8 variant_id;
@@ -243,16 +319,107 @@ struct mxt_data {
 	const struct mxt_platform_data *pdata;
 	struct mxt_object *object_table;
 	struct mxt_info info;
+	bool is_tp;
+
 	unsigned int irq;
 	unsigned int max_x;
 	unsigned int max_y;
 
+	/* max touchscreen area in terms of pixels and channels */
+	unsigned int max_area_pixels;
+	unsigned int max_area_channels;
+
+	u32 info_csum;
+	u32 config_csum;
+
 	/* Cached parameters from object table */
+	u16 T5_address;
 	u8 T6_reportid;
 	u8 T9_reportid_min;
 	u8 T9_reportid_max;
+	u8 T19_reportid;
+	u16 T44_address;
+
+	/* for fw update in bootloader */
+	struct completion bl_completion;
+
+	/* per-instance debugfs root */
+	struct dentry *dentry_dev;
+	struct dentry *dentry_deltas;
+	struct dentry *dentry_refs;
+	struct dentry *dentry_object;
+
+	/* Protect access to the T37 object buffer, used by debugfs */
+	struct mutex T37_buf_mutex;
+	u8 *T37_buf;
+	size_t T37_buf_size;
+
+	/* Saved T7 configuration
+	 * [0] = IDLEACQINT
+	 * [1] = ACTVACQINT
+	 * [2] = ACTV2IDLETO
+	 */
+	u8 T7_config[3];
+	bool T7_config_valid;
+
+	/* T7 IDLEACQINT & ACTVACQINT setting when in suspend mode*/
+	u8 suspend_acq_interval;
+
+	/* Saved T9 Ctrl field */
+	u8 T9_ctrl;
+	bool T9_ctrl_valid;
+
+	bool irq_wake;  /* irq wake is enabled */
+	/* Saved T42 Touch Suppression field */
+	u8 T42_ctrl;
+	bool T42_ctrl_valid;
+
+	/* Saved T19 GPIO config */
+	u8 T19_ctrl;
+	bool T19_ctrl_valid;
+
+	/* Protect access to the object register buffer */
+	struct mutex object_str_mutex;
+	char *object_str;
+	size_t object_str_size;
+
+	/* for auto-calibration in suspend */
+	struct completion auto_cal_completion;
+
+	/* firmware file name */
+	char *fw_file;
+
+	/* config file name */
+	char *config_file;
+
+	/* map for the tracking id currently being used */
+	bool current_id[MXT_MAX_FINGER];
+
+#if defined(CONFIG_ACPI_BUTTON)
+	/* notifier block for acpi_lid_notifier */
+	struct notifier_block lid_notifier;
+#endif
 };
 
+/* global root node of the atmel_mxt_ts debugfs directory. */
+static struct dentry *mxt_debugfs_root;
+
+static int mxt_calc_resolution(struct mxt_data *data);
+static void mxt_free_object_table(struct mxt_data *data);
+static int mxt_initialize(struct mxt_data *data);
+static int mxt_input_dev_create(struct mxt_data *data);
+static int get_touch_major_pixels(struct mxt_data *data, int touch_channels);
+
+static inline size_t mxt_obj_size(const struct mxt_object *obj)
+{
+	return obj->size + 1;
+}
+
+static inline size_t mxt_obj_instances(const struct mxt_object *obj)
+{
+	return obj->instances + 1;
+}
+
 static bool mxt_object_readable(unsigned int type)
 {
 	switch (type) {
@@ -273,6 +440,11 @@ static bool mxt_object_readable(unsigned int type)
 	case MXT_PROCI_TOUCHSUPPRESSION_T42:
 	case MXT_PROCI_STYLUS_T47:
 	case MXT_PROCG_NOISESUPPRESSION_T48:
+	case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
+	case MXT_PROCI_SHIELDLESS_T56:
+	case MXT_PROCI_EXTRATOUCHSCREENDATA_T57:
+	case MXT_PROCG_NOISESUPPRESSION_T62:
+	case MXT_PROCI_LENSBENDING_T65:
 	case MXT_SPT_COMMSCONFIG_T18:
 	case MXT_SPT_GPIOPWM_T19:
 	case MXT_SPT_SELFTEST_T25:
@@ -280,6 +452,7 @@ static bool mxt_object_readable(unsigned int type)
 	case MXT_SPT_USERDATA_T38:
 	case MXT_SPT_DIGITIZER_T43:
 	case MXT_SPT_CTECONFIG_T46:
+	case MXT_SPT_TIMER_T61:
 		return true;
 	default:
 		return false;
@@ -305,12 +478,18 @@ static bool mxt_object_writable(unsigned int type)
 	case MXT_PROCI_TOUCHSUPPRESSION_T42:
 	case MXT_PROCI_STYLUS_T47:
 	case MXT_PROCG_NOISESUPPRESSION_T48:
+	case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
+	case MXT_PROCI_SHIELDLESS_T56:
+	case MXT_PROCI_EXTRATOUCHSCREENDATA_T57:
+	case MXT_PROCG_NOISESUPPRESSION_T62:
+	case MXT_PROCI_LENSBENDING_T65:
 	case MXT_SPT_COMMSCONFIG_T18:
 	case MXT_SPT_GPIOPWM_T19:
 	case MXT_SPT_SELFTEST_T25:
 	case MXT_SPT_CTECONFIG_T28:
 	case MXT_SPT_DIGITIZER_T43:
 	case MXT_SPT_CTECONFIG_T46:
+	case MXT_SPT_TIMER_T61:
 		return true;
 	default:
 		return false;
@@ -324,19 +503,154 @@ static void mxt_dump_message(struct device *dev,
 		message->reportid, 7, message->message);
 }
 
-static int mxt_check_bootloader(struct i2c_client *client,
-				     unsigned int state)
+/*
+ * Release all the fingers that are being tracked. To avoid unwanted gestures,
+ * move all the fingers to (0,0) with largest PRESSURE and TOUCH_MAJOR.
+ * Userspace apps can use these info to filter out these events and/or cancel
+ * existing gestures.
+ */
+static void mxt_release_all_fingers(struct mxt_data *data)
+{
+	struct device *dev = &data->client->dev;
+	struct input_dev *input_dev = data->input_dev;
+	int id;
+	int max_area_channels = min(255U, data->max_area_channels);
+	int max_touch_major = get_touch_major_pixels(data, max_area_channels);
+	bool need_update = false;
+	for (id = 0; id < MXT_MAX_FINGER; id++) {
+		if (data->current_id[id]) {
+			dev_warn(dev, "Move touch %d to (0,0)\n", id);
+			input_mt_slot(input_dev, id);
+			input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
+						   true);
+			input_report_abs(input_dev, ABS_MT_POSITION_X, 0);
+			input_report_abs(input_dev, ABS_MT_POSITION_Y, 0);
+			input_report_abs(input_dev, ABS_MT_PRESSURE, 255);
+			input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
+					 max_touch_major);
+			need_update = true;
+		}
+	}
+	if (need_update)
+		input_sync(data->input_dev);
+
+	for (id = 0; id < MXT_MAX_FINGER; id++) {
+		if (data->current_id[id]) {
+			dev_warn(dev, "Release touch contact %d\n", id);
+			input_mt_slot(input_dev, id);
+			input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
+						   false);
+			data->current_id[id] = false;
+		}
+	}
+	if (need_update)
+		input_sync(data->input_dev);
+}
+
+static bool mxt_in_bootloader(struct mxt_data *data)
+{
+	struct i2c_client *client = data->client;
+	return (client->addr == MXT_BOOT_LOW || client->addr == MXT_BOOT_HIGH);
+}
+
+static int mxt_i2c_recv(struct i2c_client *client, u8 *buf, size_t count)
+{
+	int ret;
+
+	ret = i2c_master_recv(client, buf, count);
+	if (ret == count) {
+		ret = 0;
+	} else if (ret != count) {
+		ret = (ret < 0) ? ret : -EIO;
+		dev_err(&client->dev, "i2c recv failed (%d)\n", ret);
+	}
+
+	return ret;
+}
+
+static int mxt_i2c_send(struct i2c_client *client, const u8 *buf, size_t count)
+{
+	int ret;
+
+	ret = i2c_master_send(client, buf, count);
+	if (ret == count) {
+		ret = 0;
+	} else if (ret != count) {
+		ret = (ret < 0) ? ret : -EIO;
+		dev_err(&client->dev, "i2c send failed (%d)\n", ret);
+	}
+
+	return ret;
+}
+
+static int mxt_i2c_transfer(struct i2c_client *client, struct i2c_msg *msgs,
+		size_t count)
+{
+	int ret;
+
+	ret = i2c_transfer(client->adapter, msgs, count);
+	if (ret == count) {
+		ret = 0;
+	} else {
+		ret = (ret < 0) ? ret : -EIO;
+		dev_err(&client->dev, "i2c transfer failed (%d)\n", ret);
+	}
+
+	return ret;
+}
+
+static int mxt_wait_for_chg(struct mxt_data *data, unsigned int timeout_ms)
+{
+	struct device *dev = &data->client->dev;
+	struct completion *comp = &data->bl_completion;
+	unsigned long timeout = msecs_to_jiffies(timeout_ms);
+	long ret;
+
+	ret = wait_for_completion_interruptible_timeout(comp, timeout);
+	if (ret < 0) {
+		dev_err(dev, "Wait for completion interrupted.\n");
+		/*
+		 * TODO: handle -EINTR better by terminating fw update process
+		 * before returning to userspace by writing length 0x000 to
+		 * device (iff we are in WAITING_FRAME_DATA state).
+		 */
+		return -EINTR;
+	} else if (ret == 0) {
+		dev_err(dev, "Wait for completion timed out.\n");
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static int mxt_check_bootloader(struct mxt_data *data, unsigned int state)
 {
+	struct i2c_client *client = data->client;
 	u8 val;
+	int ret;
 
 recheck:
-	if (i2c_master_recv(client, &val, 1) != 1) {
-		dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
-		return -EIO;
+	if (state != MXT_WAITING_BOOTLOAD_CMD) {
+		/*
+		 * In application update mode, the interrupt
+		 * line signals state transitions. We must wait for the
+		 * CHG assertion before reading the status byte.
+		 * Once the status byte has been read, the line is deasserted.
+		 */
+		int ret = mxt_wait_for_chg(data, 300);
+		if (ret) {
+			dev_err(&client->dev, "Update wait error %d\n", ret);
+			return ret;
+		}
 	}
 
+	ret = mxt_i2c_recv(client, &val, 1);
+	if (ret)
+		return ret;
+
 	switch (state) {
 	case MXT_WAITING_BOOTLOAD_CMD:
+		dev_info(&client->dev, "bootloader version: %d\n",
+			 val & MXT_BOOT_STATUS_MASK);
 	case MXT_WAITING_FRAME_DATA:
 		val &= ~MXT_BOOT_STATUS_MASK;
 		break;
@@ -350,6 +664,8 @@ recheck:
 
 	if (val != state) {
 		dev_err(&client->dev, "Unvalid bootloader mode state\n");
+		dev_err(&client->dev, "Invalid bootloader mode state %d, %d\n",
+			val, state);
 		return -EINVAL;
 	}
 
@@ -363,24 +679,41 @@ static int mxt_unlock_bootloader(struct i2c_client *client)
 	buf[0] = MXT_UNLOCK_CMD_LSB;
 	buf[1] = MXT_UNLOCK_CMD_MSB;
 
-	if (i2c_master_send(client, buf, 2) != 2) {
-		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-		return -EIO;
-	}
-
-	return 0;
+	return mxt_i2c_send(client, buf, 2);
 }
 
 static int mxt_fw_write(struct i2c_client *client,
 			     const u8 *data, unsigned int frame_size)
 {
-	if (i2c_master_send(client, data, frame_size) != frame_size) {
-		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-		return -EIO;
-	}
+	return mxt_i2c_send(client, data, frame_size);
+}
 
-	return 0;
+#ifdef DEBUG
+#define DUMP_LEN	16
+static void mxt_dump_xfer(struct device *dev, const char *func, u16 reg,
+			  u16 len, const u8 *val)
+{
+	/* Rough guess for string size */
+	char str[DUMP_LEN * 3 + 2];
+	int i;
+	size_t n;
+
+	for (i = 0, n = 0; i < len; i++) {
+		n += snprintf(&str[n], sizeof(str) - n, "%02x ", val[i]);
+		if ((i + 1) % DUMP_LEN == 0 || (i + 1) == len) {
+			dev_dbg(dev,
+				"%s(reg: %d len: %d offset: 0x%02x): %s\n",
+				func, reg, len, (i / DUMP_LEN) * DUMP_LEN,
+				str);
+			n = 0;
+		}
+	}
 }
+#undef DUMP_LEN
+#else
+static void mxt_dump_xfer(struct device *dev, const char *func, u16 reg,
+			  u16 len, const u8 *val) { }
+#endif
 
 static int __mxt_read_reg(struct i2c_client *client,
 			       u16 reg, u16 len, void *val)
@@ -404,24 +737,13 @@ static int __mxt_read_reg(struct i2c_client *client,
 	xfer[1].len = len;
 	xfer[1].buf = val;
 
-	ret = i2c_transfer(client->adapter, xfer, 2);
-	if (ret == 2) {
-		ret = 0;
-	} else {
-		if (ret >= 0)
-			ret = -EIO;
-		dev_err(&client->dev, "%s: i2c transfer failed (%d)\n",
-			__func__, ret);
-	}
+	ret = mxt_i2c_transfer(client, xfer, 2);
+	if (ret == 0)
+		mxt_dump_xfer(&client->dev, __func__, reg, len, val);
 
 	return ret;
 }
 
-static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
-{
-	return __mxt_read_reg(client, reg, 1, val);
-}
-
 static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
 			   const void *val)
 {
@@ -438,16 +760,8 @@ static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
 	buf[1] = (reg >> 8) & 0xff;
 	memcpy(&buf[2], val, len);
 
-	ret = i2c_master_send(client, buf, count);
-	if (ret == count) {
-		ret = 0;
-	} else {
-		if (ret >= 0)
-			ret = -EIO;
-		dev_err(&client->dev, "%s: i2c send failed (%d)\n",
-			__func__, ret);
-	}
-
+	mxt_dump_xfer(&client->dev, __func__, reg, len, val);
+	ret = mxt_i2c_send(client, buf, count);
 	kfree(buf);
 	return ret;
 }
@@ -473,33 +787,66 @@ mxt_get_object(struct mxt_data *data, u8 type)
 	return NULL;
 }
 
-static int mxt_read_message(struct mxt_data *data,
-				 struct mxt_message *message)
+static int mxt_read_num_messages(struct mxt_data *data, u8 *count)
 {
-	struct mxt_object *object;
-	u16 reg;
-
-	object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
-	if (!object)
-		return -EINVAL;
+	/* TODO: Optimization: read first message along with message count */
+	return __mxt_read_reg(data->client, data->T44_address, 1, count);
+}
 
-	reg = object->start_address;
-	return __mxt_read_reg(data->client, reg,
-			sizeof(struct mxt_message), message);
+static int mxt_read_messages(struct mxt_data *data, u8 count,
+			     struct mxt_message *messages)
+{
+	return __mxt_read_reg(data->client, data->T5_address,
+			sizeof(struct mxt_message) * count, messages);
 }
 
-static int mxt_write_object(struct mxt_data *data,
-				 u8 type, u8 offset, u8 val)
+static int mxt_write_obj_instance(struct mxt_data *data, u8 type, u8 instance,
+		u8 offset, u8 val)
 {
 	struct mxt_object *object;
 	u16 reg;
 
 	object = mxt_get_object(data, type);
-	if (!object || offset >= object->size + 1)
+	if (!object || offset >= mxt_obj_size(object) ||
+	    instance >= mxt_obj_instances(object))
 		return -EINVAL;
 
-	reg = object->start_address;
-	return mxt_write_reg(data->client, reg + offset, val);
+	reg = object->start_address + instance * mxt_obj_size(object) + offset;
+	return mxt_write_reg(data->client, reg, val);
+}
+
+static int mxt_write_object(struct mxt_data *data, u8 type, u8 offset, u8 val)
+{
+	return mxt_write_obj_instance(data, type, 0, offset, val);
+}
+
+static void mxt_input_button(struct mxt_data *data, struct mxt_message *message)
+{
+	struct device *dev = &data->client->dev;
+	struct input_dev *input = data->input_dev;
+	bool button;
+
+	/* Active-low switch */
+	button = !(message->message[0] & MXT_GPIO3_MASK);
+	input_report_key(input, BTN_LEFT, button);
+	dev_dbg(dev, "Button state: %d\n", button);
+}
+
+/*
+ * Assume a circle touch contact and use the diameter as the touch major.
+ * touch_pixels = touch_channels * (max_area_pixels / max_area_channels)
+ * touch_pixels = pi * (touch_major / 2) ^ 2;
+ */
+static int get_touch_major_pixels(struct mxt_data *data, int touch_channels)
+{
+	int touch_pixels;
+
+	if (data->max_area_channels == 0)
+		return 0;
+
+	touch_pixels = DIV_ROUND_CLOSEST(touch_channels * data->max_area_pixels,
+					 data->max_area_channels);
+	return int_sqrt(DIV_ROUND_CLOSEST(touch_pixels * 100, 314)) * 2;
 }
 
 static void mxt_input_touchevent(struct mxt_data *data,
@@ -512,6 +859,8 @@ static void mxt_input_touchevent(struct mxt_data *data,
 	int y;
 	int area;
 	int pressure;
+	int touch_major;
+	int vector1, vector2;
 
 	x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
 	y = (message->message[2] << 4) | ((message->message[3] & 0xf));
@@ -521,10 +870,15 @@ static void mxt_input_touchevent(struct mxt_data *data,
 		y = y >> 2;
 
 	area = message->message[4];
+	touch_major = get_touch_major_pixels(data, area);
 	pressure = message->message[5];
 
+	/* The two vector components are 4-bit signed ints (2s complement) */
+	vector1 = (signed)((signed char)message->message[6]) >> 4;
+	vector2 = (signed)((signed char)(message->message[6] << 4)) >> 4;
+
 	dev_dbg(dev,
-		"[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u\n",
+		"[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u vector: [%d,%d]\n",
 		id,
 		(status & MXT_DETECT) ? 'D' : '.',
 		(status & MXT_PRESS) ? 'P' : '.',
@@ -534,17 +888,19 @@ static void mxt_input_touchevent(struct mxt_data *data,
 		(status & MXT_AMP) ? 'A' : '.',
 		(status & MXT_SUPPRESS) ? 'S' : '.',
 		(status & MXT_UNGRIP) ? 'U' : '.',
-		x, y, area, pressure);
+		x, y, area, pressure, vector1, vector2);
 
 	input_mt_slot(input_dev, id);
 	input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
 				   status & MXT_DETECT);
+	data->current_id[id] = status & MXT_DETECT;
 
 	if (status & MXT_DETECT) {
 		input_report_abs(input_dev, ABS_MT_POSITION_X, x);
 		input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
 		input_report_abs(input_dev, ABS_MT_PRESSURE, pressure);
-		input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, area);
+		input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, touch_major);
+		/* TODO: Use vector to report ORIENTATION & TOUCH_MINOR */
 	}
 }
 
@@ -559,47 +915,177 @@ static bool mxt_is_T9_message(struct mxt_data *data, struct mxt_message *msg)
 	return (id >= data->T9_reportid_min && id <= data->T9_reportid_max);
 }
 
-static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+static int mxt_proc_messages(struct mxt_data *data, u8 count, bool report)
 {
-	struct mxt_data *data = dev_id;
-	struct mxt_message message;
-	const u8 *payload = &message.message[0];
 	struct device *dev = &data->client->dev;
 	u8 reportid;
 	bool update_input = false;
+	struct mxt_message *messages, *msg;
+	int ret;
 
-	do {
-		if (mxt_read_message(data, &message)) {
-			dev_err(dev, "Failed to read message\n");
-			goto end;
-		}
+	messages = kcalloc(count, sizeof(*messages), GFP_KERNEL);
+	if (!messages)
+		return -ENOMEM;
+
+	ret = mxt_read_messages(data, count, messages);
+	if (ret) {
+		dev_err(dev, "Failed to read %u messages (%d).\n", count, ret);
+		goto out;
+	}
+	if (!report)
+		goto out;
 
-		reportid = message.reportid;
+	for (msg = messages; msg < &messages[count]; msg++) {
+		mxt_dump_message(dev, msg);
+		reportid = msg->reportid;
 
 		if (reportid == data->T6_reportid) {
+			const u8 *payload = &msg->message[0];
 			u8 status = payload[0];
-			unsigned csum = mxt_extract_T6_csum(&payload[1]);
+			data->config_csum = mxt_extract_T6_csum(&payload[1]);
 			dev_dbg(dev, "Status: %02x Config Checksum: %06x\n",
-				status, csum);
-		} else if (mxt_is_T9_message(data, &message)) {
+				status, data->config_csum);
+			if (status == 0x00)
+				complete(&data->auto_cal_completion);
+		} else if (mxt_is_T9_message(data, msg)) {
 			int id = reportid - data->T9_reportid_min;
-			mxt_input_touchevent(data, &message, id);
+			mxt_input_touchevent(data, msg, id);
+			update_input = true;
+		} else if (msg->reportid == data->T19_reportid) {
+			mxt_input_button(data, msg);
 			update_input = true;
-		} else {
-			mxt_dump_message(dev, &message);
 		}
-	} while (reportid != 0xff);
+	}
 
 	if (update_input) {
 		input_mt_report_pointer_emulation(data->input_dev, false);
 		input_sync(data->input_dev);
 	}
 
-end:
+out:
+	kfree(messages);
+	return ret;
+}
+
+static int mxt_handle_messages(struct mxt_data *data, bool report)
+{
+	struct device *dev = &data->client->dev;
+	int ret;
+	u8 count;
+
+	ret = mxt_read_num_messages(data, &count);
+	if (ret) {
+		dev_err(dev, "Failed to read message count (%d).\n", ret);
+		return ret;
+	}
+
+	if (count > 0)
+		ret = mxt_proc_messages(data, count, report);
+
+	return ret;
+}
+
+static int mxt_enter_bl(struct mxt_data *data)
+{
+	struct i2c_client *client = data->client;
+	struct device *dev = &client->dev;
+	int ret;
+
+	if (mxt_in_bootloader(data))
+		return 0;
+
+	disable_irq(data->irq);
+
+	/* Change to the bootloader mode */
+	ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+			       MXT_COMMAND_RESET, MXT_BOOT_VALUE);
+	if (ret) {
+		enable_irq(data->irq);
+		return ret;
+	}
+
+	/* Change to slave address of bootloader */
+	if (client->addr == MXT_APP_LOW)
+		client->addr = MXT_BOOT_LOW;
+	else
+		client->addr = MXT_BOOT_HIGH;
+
+	/* Free any driver state. It will get reinitialized after fw update. */
+	mxt_free_object_table(data);
+	if (data->input_dev) {
+		input_unregister_device(data->input_dev);
+		data->input_dev = NULL;
+	}
+
+	INIT_COMPLETION(data->bl_completion);
+	enable_irq(data->irq);
+
+	/* Wait for CHG assert to indicate successful reset into bootloader */
+	ret = mxt_wait_for_chg(data, MXT_RESET_TIME);
+	if (ret) {
+		dev_err(dev, "Failed waiting for reset to bootloader.\n");
+		if (client->addr == MXT_BOOT_LOW)
+			client->addr = MXT_APP_LOW;
+		else
+			client->addr = MXT_APP_HIGH;
+		return ret;
+	}
+	return 0;
+}
+
+static void mxt_exit_bl(struct mxt_data *data)
+{
+	struct i2c_client *client = data->client;
+	struct device *dev = &client->dev;
+	int error;
+
+	if (!mxt_in_bootloader(data))
+		return;
+
+	/* Wait for reset */
+	mxt_wait_for_chg(data, MXT_FWRESET_TIME);
+
+	disable_irq(data->irq);
+	if (client->addr == MXT_BOOT_LOW)
+		client->addr = MXT_APP_LOW;
+	else
+		client->addr = MXT_APP_HIGH;
+
+	error = mxt_initialize(data);
+	if (error) {
+		dev_err(dev, "Failed to initialize on exit bl. error = %d\n",
+			error);
+		return;
+	}
+
+	error = mxt_input_dev_create(data);
+	if (error) {
+		dev_err(dev, "Create input dev failed after init. error = %d\n",
+			error);
+		return;
+	}
+
+	error = mxt_handle_messages(data, false);
+	if (error)
+		dev_err(dev, "Failed to clear CHG after init. error = %d\n",
+			error);
+	enable_irq(data->irq);
+}
+
+static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+{
+	struct mxt_data *data = dev_id;
+
+	if (mxt_in_bootloader(data)) {
+		/* bootloader state transition completion */
+		complete(&data->bl_completion);
+	} else {
+		mxt_handle_messages(data, true);
+	}
 	return IRQ_HANDLED;
 }
 
-static int mxt_check_reg_init(struct mxt_data *data)
+static int mxt_apply_pdata_config(struct mxt_data *data)
 {
 	const struct mxt_platform_data *pdata = data->pdata;
 	struct mxt_object *object;
@@ -609,7 +1095,7 @@ static int mxt_check_reg_init(struct mxt_data *data)
 	int ret;
 
 	if (!pdata->config) {
-		dev_dbg(dev, "No cfg data defined, skipping reg init\n");
+		dev_info(dev, "No cfg data defined, skipping reg init\n");
 		return 0;
 	}
 
@@ -619,7 +1105,7 @@ static int mxt_check_reg_init(struct mxt_data *data)
 		if (!mxt_object_writable(object->type))
 			continue;
 
-		size = (object->size + 1) * (object->instances + 1);
+		size = mxt_obj_size(object) * mxt_obj_instances(object);
 		if (index + size > pdata->config_length) {
 			dev_err(dev, "Not enough config data!\n");
 			return -EINVAL;
@@ -635,32 +1121,21 @@ static int mxt_check_reg_init(struct mxt_data *data)
 	return 0;
 }
 
-static int mxt_make_highchg(struct mxt_data *data)
+static int mxt_handle_pdata(struct mxt_data *data)
 {
+	const struct mxt_platform_data *pdata = data->pdata;
 	struct device *dev = &data->client->dev;
-	struct mxt_message message;
-	int count = 10;
-	int error;
-
-	/* Read dummy message to make high CHG pin */
-	do {
-		error = mxt_read_message(data, &message);
-		if (error)
-			return error;
-	} while (message.reportid != 0xff && --count);
+	u8 voltage;
+	int ret;
 
-	if (!count) {
-		dev_err(dev, "CHG pin isn't cleared\n");
-		return -EBUSY;
+	if (!pdata) {
+		dev_info(dev, "No platform data provided\n");
+		return 0;
 	}
 
-	return 0;
-}
-
-static void mxt_handle_pdata(struct mxt_data *data)
-{
-	const struct mxt_platform_data *pdata = data->pdata;
-	u8 voltage;
+	ret = mxt_apply_pdata_config(data);
+	if (ret)
+		return ret;
 
 	/* Set touchscreen lines */
 	mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_XSIZE,
@@ -703,12 +1178,86 @@ static void mxt_handle_pdata(struct mxt_data *data)
 		mxt_write_object(data, MXT_SPT_CTECONFIG_T28,
 				MXT_CTE_VOLTAGE, voltage);
 	}
+
+	/* Backup to memory */
+	ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+			       MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
+	if (ret)
+		return ret;
+	msleep(MXT_BACKUP_TIME);
+
+	return 0;
 }
 
-static int mxt_get_info(struct mxt_data *data)
+/* Update 24-bit CRC with two new bytes of data */
+static u32 crc24_step(u32 crc, u8 byte1, u8 byte2)
 {
-	struct i2c_client *client = data->client;
-	struct mxt_info *info = &data->info;
+	const u32 crcpoly = 0x80001b;
+	u16 data = byte1 | (byte2 << 8);
+	u32 result = data ^ (crc << 1);
+
+	/* XOR result with crcpoly if bit 25 is set (overflow occurred) */
+	if (result & 0x01000000)
+		result ^= crcpoly;
+
+	return result & 0x00ffffff;
+}
+
+static u32 crc24(u32 crc, const u8 *data, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len - 1; i += 2)
+		crc = crc24_step(crc, data[i], data[i + 1]);
+
+	/* If there were an odd number of bytes pad with 0 */
+	if (i < len)
+		crc = crc24_step(crc, data[i], 0);
+
+	return crc;
+}
+
+static int mxt_verify_info_block_csum(struct mxt_data *data)
+{
+	struct i2c_client *client = data->client;
+	struct device *dev = &client->dev;
+	size_t object_table_size, info_block_size;
+	u32 crc = 0;
+	u8 *info_block;
+	int ret = 0;
+
+	object_table_size = data->info.object_num * MXT_OBJECT_SIZE;
+	info_block_size = sizeof(data->info) + object_table_size;
+	info_block = kmalloc(info_block_size, GFP_KERNEL);
+	if (!info_block)
+		return -ENOMEM;
+
+	/*
+	 * Information Block CRC is computed over both ID info and Object Table
+	 * So concat them in a temporary buffer, before computing CRC.
+	 * TODO: refactor how the info block is read from the device such
+	 * that it ends up in a single buffer and this copy is not needed.
+	 */
+	memcpy(info_block, &data->info, sizeof(data->info));
+	memcpy(&info_block[sizeof(data->info)], data->object_table,
+			object_table_size);
+
+	crc = crc24(crc, info_block, info_block_size);
+
+	if (crc != data->info_csum) {
+		dev_err(dev, "Information Block CRC mismatch: %06x != %06x\n",
+			data->info_csum, crc);
+		ret = -EINVAL;
+	}
+
+	kfree(info_block);
+	return ret;
+}
+
+static int mxt_get_info(struct mxt_data *data)
+{
+	struct i2c_client *client = data->client;
+	struct mxt_info *info = &data->info;
 	int error;
 
 	/* Read 7-byte info block starting at address 0 */
@@ -722,10 +1271,12 @@ static int mxt_get_info(struct mxt_data *data)
 static int mxt_get_object_table(struct mxt_data *data)
 {
 	struct i2c_client *client = data->client;
+	struct device *dev = &data->client->dev;
 	size_t table_size;
 	int error;
 	int i;
 	u8 reportid;
+	u8 csum[3];
 
 	table_size = data->info.object_num * sizeof(struct mxt_object);
 	error = __mxt_read_reg(client, MXT_OBJECT_START, table_size,
@@ -733,6 +1284,22 @@ static int mxt_get_object_table(struct mxt_data *data)
 	if (error)
 		return error;
 
+	/*
+	 * Read Information Block checksum from 3 bytes immediately following
+	 * info block
+	 */
+	error = __mxt_read_reg(client, MXT_OBJECT_START + table_size,
+			sizeof(csum), csum);
+	if (error)
+		return error;
+
+	data->info_csum = csum[0] | (csum[1] << 8) | (csum[2] << 16);
+	dev_info(dev, "Information Block Checksum = %06x\n", data->info_csum);
+
+	error = mxt_verify_info_block_csum(data);
+	if (error)
+		return error;
+
 	/* Valid Report IDs start counting from 1 */
 	reportid = 1;
 	for (i = 0; i < data->info.object_num; i++) {
@@ -744,7 +1311,7 @@ static int mxt_get_object_table(struct mxt_data *data)
 		if (object->num_report_ids) {
 			min_id = reportid;
 			reportid += object->num_report_ids *
-					(object->instances + 1);
+					mxt_obj_instances(object);
 			max_id = reportid - 1;
 		} else {
 			min_id = 0;
@@ -752,11 +1319,15 @@ static int mxt_get_object_table(struct mxt_data *data)
 		}
 
 		dev_dbg(&data->client->dev,
-			"Type %2d Start %3d Size %3d Instances %2d ReportIDs %3u : %3u\n",
-			object->type, object->start_address, object->size + 1,
-			object->instances + 1, min_id, max_id);
+			"Type %2d Start %3d Size %3zu Instances %2zu ReportIDs %3u : %3u\n",
+			object->type, object->start_address,
+			mxt_obj_size(object), mxt_obj_instances(object),
+			min_id, max_id);
 
 		switch (object->type) {
+		case MXT_GEN_MESSAGE_T5:
+			data->T5_address = object->start_address;
+			break;
 		case MXT_GEN_COMMAND_T6:
 			data->T6_reportid = min_id;
 			break;
@@ -764,6 +1335,12 @@ static int mxt_get_object_table(struct mxt_data *data)
 			data->T9_reportid_min = min_id;
 			data->T9_reportid_max = max_id;
 			break;
+		case MXT_SPT_GPIOPWM_T19:
+			data->T19_reportid = min_id;
+			break;
+		case MXT_SPT_MESSAGECOUNT_T44:
+			data->T44_address = object->start_address;
+			break;
 		}
 	}
 
@@ -785,7 +1362,6 @@ static int mxt_initialize(struct mxt_data *data)
 	struct i2c_client *client = data->client;
 	struct mxt_info *info = &data->info;
 	int error;
-	u8 val;
 
 	error = mxt_get_info(data);
 	if (error)
@@ -804,34 +1380,17 @@ static int mxt_initialize(struct mxt_data *data)
 	if (error)
 		goto err_free_object_table;
 
-	/* Check register init values */
-	error = mxt_check_reg_init(data);
+	/* Apply config from platform data */
+	error = mxt_handle_pdata(data);
 	if (error)
 		goto err_free_object_table;
 
-	mxt_handle_pdata(data);
-
-	/* Backup to memory */
-	mxt_write_object(data, MXT_GEN_COMMAND_T6,
-			MXT_COMMAND_BACKUPNV,
-			MXT_BACKUP_VALUE);
-	msleep(MXT_BACKUP_TIME);
-
 	/* Soft reset */
-	mxt_write_object(data, MXT_GEN_COMMAND_T6,
-			MXT_COMMAND_RESET, 1);
-	msleep(MXT_RESET_TIME);
-
-	/* Update matrix size at info struct */
-	error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
-	if (error)
-		goto err_free_object_table;
-	info->matrix_xsize = val;
-
-	error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
+	error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+				 MXT_COMMAND_RESET, 1);
 	if (error)
 		goto err_free_object_table;
-	info->matrix_ysize = val;
+	msleep(MXT_RESET_TIME);
 
 	dev_info(&client->dev,
 			"Family ID: %u Variant ID: %u Major.Minor.Build: %u.%u.%02X\n",
@@ -843,6 +1402,10 @@ static int mxt_initialize(struct mxt_data *data)
 			info->matrix_xsize, info->matrix_ysize,
 			info->object_num);
 
+	error = mxt_calc_resolution(data);
+	if (error)
+		return error;
+
 	return 0;
 
 err_free_object_table:
@@ -850,233 +1413,1187 @@ err_free_object_table:
 	return error;
 }
 
-static void mxt_calc_resolution(struct mxt_data *data)
+static int mxt_calc_resolution(struct mxt_data *data)
 {
-	unsigned int max_x = data->pdata->x_size - 1;
-	unsigned int max_y = data->pdata->y_size - 1;
+	struct i2c_client *client = data->client;
+	u8 orient;
+	__le16 xyrange[2];
+	unsigned int max_x, max_y;
+	u8 xylines[2];
+	int ret;
+
+	struct mxt_object *T9 = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
+	if (T9 == NULL)
+		return -EINVAL;
+
+	/* Get touchscreen resolution */
+	ret = __mxt_read_reg(client, T9->start_address + MXT_TOUCH_XRANGE_LSB,
+			4, xyrange);
+	if (ret)
+		return ret;
+
+	ret = __mxt_read_reg(client, T9->start_address + MXT_TOUCH_ORIENT,
+			1, &orient);
+	if (ret)
+		return ret;
+
+	ret = __mxt_read_reg(client, T9->start_address + MXT_TOUCH_XSIZE,
+			2, xylines);
+	if (ret)
+		return ret;
+
+	max_x = le16_to_cpu(xyrange[0]);
+	max_y = le16_to_cpu(xyrange[1]);
 
-	if (data->pdata->orient & MXT_XY_SWITCH) {
+	if (orient & MXT_XY_SWITCH) {
 		data->max_x = max_y;
 		data->max_y = max_x;
 	} else {
 		data->max_x = max_x;
 		data->max_y = max_y;
 	}
-}
 
-/* Firmware Version is returned as Major.Minor.Build */
-static ssize_t mxt_fw_version_show(struct device *dev,
-				   struct device_attribute *attr, char *buf)
-{
-	struct mxt_data *data = dev_get_drvdata(dev);
-	struct mxt_info *info = &data->info;
-	return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n",
-			 info->version >> 4, info->version & 0xf, info->build);
-}
+	data->max_area_pixels = max_x * max_y;
+	data->max_area_channels = xylines[0] * xylines[1];
 
-/* Hardware Version is returned as FamilyID.VariantID */
-static ssize_t mxt_hw_version_show(struct device *dev,
-				   struct device_attribute *attr, char *buf)
-{
-	struct mxt_data *data = dev_get_drvdata(dev);
-	struct mxt_info *info = &data->info;
-	return scnprintf(buf, PAGE_SIZE, "%u.%u\n",
-			 info->family_id, info->variant_id);
+	return 0;
 }
 
-static ssize_t mxt_show_instance(char *buf, int count,
-				 struct mxt_object *object, int instance,
-				 const u8 *val)
+/*
+ * Atmel Raw Config File Format
+ *
+ * The first four lines of the raw config file contain:
+ *  1) Version
+ *  2) Chip ID Information (first 7 bytes of device memory)
+ *  3) Chip Information Block 24-bit CRC Checksum
+ *  4) Chip Configuration 24-bit CRC Checksum
+ *
+ * The rest of the file consists of one line per object instance:
+ *   <TYPE> <INSTANCE> <SIZE> <CONTENTS>
+ *
+ *  <TYPE> - 2-byte object type as hex
+ *  <INSTANCE> - 2-byte object instance number as hex
+ *  <SIZE> - 2-byte object size as hex
+ *  <CONTENTS> - array of <SIZE> 1-byte hex values
+ */
+static int mxt_cfg_verify_hdr(struct mxt_data *data, char **config)
 {
-	int i;
+	struct i2c_client *client = data->client;
+	struct device *dev = &client->dev;
+	struct mxt_info info;
+	char *token;
+	int ret = 0;
+	u32 crc;
+
+	/* Process the first four lines of the file*/
+	/* 1) Version */
+	token = strsep(config, "\n");
+	dev_info(dev, "Config File: Version = %s\n", token ?: "<null>");
+	if (!token ||
+	    strncmp(token, MXT_CONFIG_VERSION, strlen(MXT_CONFIG_VERSION))) {
+		dev_err(dev, "Invalid config file: Bad Version\n");
+		return -EINVAL;
+	}
+
+	/* 2) Chip ID */
+	token = strsep(config, "\n");
+	if (!token) {
+		dev_err(dev, "Invalid config file: No Chip ID\n");
+		return -EINVAL;
+	}
+	ret = sscanf(token, "%hhx %hhx %hhx %hhx %hhx %hhx %hhx",
+		     &info.family_id, &info.variant_id,
+		     &info.version, &info.build, &info.matrix_xsize,
+		     &info.matrix_ysize, &info.object_num);
+	dev_info(dev, "Config File: Chip ID = %02x %02x %02x %02x %02x %02x %02x\n",
+		info.family_id, info.variant_id, info.version, info.build,
+		info.matrix_xsize, info.matrix_ysize, info.object_num);
+	if (ret != 7 ||
+	    info.family_id != data->info.family_id ||
+	    info.variant_id != data->info.variant_id ||
+	    info.version != data->info.version ||
+	    info.build != data->info.build ||
+	    info.matrix_xsize != data->info.matrix_xsize ||
+	    info.matrix_ysize != data->info.matrix_ysize ||
+	    info.object_num != data->info.object_num) {
+		dev_err(dev, "Invalid config file: Chip ID info mismatch\n");
+		dev_err(dev, "Chip Info: %02x %02x %02x %02x %02x %02x %02x\n",
+			data->info.family_id, data->info.variant_id,
+			data->info.version, data->info.build,
+			data->info.matrix_xsize, data->info.matrix_ysize,
+			data->info.object_num);
+		return -EINVAL;
+	}
 
-	if (object->instances > 0)
-		count += scnprintf(buf + count, PAGE_SIZE - count,
-				   "Instance %u\n", instance);
+	/* 3) Info Block CRC */
+	token = strsep(config, "\n");
+	if (!token) {
+		dev_err(dev, "Invalid config file: No Info Block CRC\n");
+		return -EINVAL;
+	}
+	ret = sscanf(token, "%x", &crc);
+	dev_info(dev, "Config File: Info Block CRC = %06x\n", crc);
+	if (ret != 1 || crc != data->info_csum) {
+		dev_err(dev, "Invalid config file: Bad Info Block CRC\n");
+		return -EINVAL;
+	}
 
-	for (i = 0; i < object->size + 1; i++)
-		count += scnprintf(buf + count, PAGE_SIZE - count,
-				"\t[%2u]: %02x (%d)\n", i, val[i], val[i]);
-	count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
+	/* 4) Config CRC */
+	/*
+	 * Parse but don't verify against current config;
+	 * TODO: Verify against CRC of rest of file?
+	 */
+	token = strsep(config, "\n");
+	if (!token) {
+		dev_err(dev, "Invalid config file: No Config CRC\n");
+		return -EINVAL;
+	}
+	ret = sscanf(token, "%x", &crc);
+	dev_info(dev, "Config File: Config CRC = %06x\n", crc);
+	if (ret != 1) {
+		dev_err(dev, "Invalid config file: Bad Config CRC\n");
+		return -EINVAL;
+	}
 
-	return count;
+	return 0;
 }
 
-static ssize_t mxt_object_show(struct device *dev,
-				    struct device_attribute *attr, char *buf)
+static int mxt_cfg_proc_line(struct mxt_data *data, const char *line,
+			     struct list_head *cfg_list)
 {
-	struct mxt_data *data = dev_get_drvdata(dev);
+	int ret;
+	u16 type, instance, size;
+	int len;
+	struct mxt_cfg_file_line *cfg_line;
 	struct mxt_object *object;
-	int count = 0;
-	int i, j;
-	int error;
-	u8 *obuf;
+	u8 *content;
+	size_t i;
 
-	/* Pre-allocate buffer large enough to hold max sized object. */
-	obuf = kmalloc(256, GFP_KERNEL);
-	if (!obuf)
+	ret = sscanf(line, "%hx %hx %hx%n", &type, &instance, &size, &len);
+	/* Skip unparseable lines */
+	if (ret < 3)
+		return 0;
+	/* Only support 1-byte types */
+	if (type > 0xff)
+		return -EINVAL;
+
+	/* Supplied object MUST be a valid instance and match object size */
+	object = mxt_get_object(data, type);
+	if (!object || instance > object->instances || size != object->size)
+		return -EINVAL;
+
+	content = kmalloc(size, GFP_KERNEL);
+	if (!content)
 		return -ENOMEM;
 
-	error = 0;
-	for (i = 0; i < data->info.object_num; i++) {
-		object = data->object_table + i;
+	for (i = 0; i < size; i++) {
+		line += len;
+		ret = sscanf(line, "%hhx%n", &content[i], &len);
+		if (ret < 1) {
+			ret = -EINVAL;
+			goto free_content;
+		}
+	}
 
-		if (!mxt_object_readable(object->type))
-			continue;
+	cfg_line = kzalloc(sizeof(*cfg_line), GFP_KERNEL);
+	if (!cfg_line) {
+		ret = -ENOMEM;
+		goto free_content;
+	}
+	INIT_LIST_HEAD(&cfg_line->list);
+	cfg_line->addr = object->start_address + instance * object->size;
+	cfg_line->size = object->size;
+	cfg_line->content = content;
+	list_add_tail(&cfg_line->list, cfg_list);
+
+	return 0;
 
-		count += scnprintf(buf + count, PAGE_SIZE - count,
-				"T%u:\n", object->type);
+free_content:
+	kfree(content);
+	return ret;
+}
 
-		for (j = 0; j < object->instances + 1; j++) {
-			u16 size = object->size + 1;
-			u16 addr = object->start_address + j * size;
+static int mxt_cfg_proc_data(struct mxt_data *data, char **config)
+{
+	struct i2c_client *client = data->client;
+	struct device *dev = &client->dev;
+	char *line;
+	int ret = 0;
+	struct list_head cfg_lines;
+	struct mxt_cfg_file_line *cfg_line, *cfg_line_tmp;
+
+	INIT_LIST_HEAD(&cfg_lines);
+
+	while ((line = strsep(config, "\n"))) {
+		ret = mxt_cfg_proc_line(data, line, &cfg_lines);
+		if (ret < 0)
+			goto free_objects;
+	}
 
-			error = __mxt_read_reg(data->client, addr, size, obuf);
-			if (error)
-				goto done;
+	list_for_each_entry(cfg_line, &cfg_lines, list) {
+		dev_dbg(dev, "Addr = %u Size = %u\n",
+			cfg_line->addr, cfg_line->size);
+		print_hex_dump(KERN_DEBUG, "atmel_mxt_ts: ", DUMP_PREFIX_OFFSET,
+			       16, 1, cfg_line->content, cfg_line->size, false);
 
-			count = mxt_show_instance(buf, count, object, j, obuf);
-		}
+		ret = __mxt_write_reg(client, cfg_line->addr, cfg_line->size,
+				cfg_line->content);
+		if (ret)
+			break;
 	}
 
-done:
-	kfree(obuf);
-	return error ?: count;
+free_objects:
+	list_for_each_entry_safe(cfg_line, cfg_line_tmp, &cfg_lines, list) {
+		list_del(&cfg_line->list);
+		kfree(cfg_line->content);
+		kfree(cfg_line);
+	}
+	return ret;
 }
 
-static int mxt_load_fw(struct device *dev, const char *fn)
+static int mxt_load_config(struct mxt_data *data, const char *fn)
 {
-	struct mxt_data *data = dev_get_drvdata(dev);
 	struct i2c_client *client = data->client;
+	struct device *dev = &client->dev;
 	const struct firmware *fw = NULL;
-	unsigned int frame_size;
-	unsigned int pos = 0;
-	int ret;
+	int ret, ret2;
+	char *cfg_copy = NULL;
+	char *running;
 
 	ret = request_firmware(&fw, fn, dev);
 	if (ret) {
-		dev_err(dev, "Unable to open firmware %s\n", fn);
+		dev_err(dev, "Unable to open config file %s\n", fn);
 		return ret;
 	}
 
-	/* Change to the bootloader mode */
-	mxt_write_object(data, MXT_GEN_COMMAND_T6,
-			MXT_COMMAND_RESET, MXT_BOOT_VALUE);
-	msleep(MXT_RESET_TIME);
-
-	/* Change to slave address of bootloader */
-	if (client->addr == MXT_APP_LOW)
-		client->addr = MXT_BOOT_LOW;
-	else
-		client->addr = MXT_BOOT_HIGH;
+	dev_info(dev, "Using config file %s (size = %zu)\n", fn, fw->size);
 
-	ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
-	if (ret)
-		goto out;
+	/* Make a mutable, '\0'-terminated copy of the config file */
+	cfg_copy = kmalloc(fw->size + 1, GFP_KERNEL);
+	if (!cfg_copy) {
+		ret = -ENOMEM;
+		goto err_alloc_copy;
+	}
+	memcpy(cfg_copy, fw->data, fw->size);
+	cfg_copy[fw->size] = '\0';
 
-	/* Unlock bootloader */
-	mxt_unlock_bootloader(client);
+	/* Verify config file header (after which running points to data) */
+	running = cfg_copy;
+	ret = mxt_cfg_verify_hdr(data, &running);
+	if (ret) {
+		dev_err(dev, "Error verifying config header (%d)\n", ret);
+		goto free_cfg_copy;
+	}
 
-	while (pos < fw->size) {
-		ret = mxt_check_bootloader(client,
-						MXT_WAITING_FRAME_DATA);
-		if (ret)
-			goto out;
+	disable_irq(data->irq);
 
-		frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
+	if (data->input_dev) {
+		input_unregister_device(data->input_dev);
+		data->input_dev = NULL;
+	}
 
-		/* We should add 2 at frame size as the the firmware data is not
-		 * included the CRC bytes.
-		 */
-		frame_size += 2;
+	/* Write configuration */
+	ret = mxt_cfg_proc_data(data, &running);
+	if (ret) {
+		dev_err(dev, "Error writing config file (%d)\n", ret);
+		goto register_input_dev;
+	}
 
-		/* Write one frame to device */
-		mxt_fw_write(client, fw->data + pos, frame_size);
+	/* Backup nvram */
+	ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+			       MXT_COMMAND_BACKUPNV,
+			       MXT_BACKUP_VALUE);
+	if (ret) {
+		dev_err(dev, "Error backup to nvram (%d)\n", ret);
+		goto register_input_dev;
+	}
+	msleep(MXT_BACKUP_TIME);
 
-		ret = mxt_check_bootloader(client,
-						MXT_FRAME_CRC_PASS);
-		if (ret)
-			goto out;
+	/* Reset device */
+	ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+			       MXT_COMMAND_RESET, 1);
+	if (ret) {
+		dev_err(dev, "Error resetting device (%d)\n", ret);
+		goto register_input_dev;
+	}
+	msleep(MXT_RESET_TIME);
 
-		pos += frame_size;
+register_input_dev:
+	ret2 = mxt_input_dev_create(data);
+	if (ret2) {
+		dev_err(dev, "Error creating input_dev (%d)\n", ret2);
+		ret = ret2;
+	}
 
-		dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
+	/* Clear message buffer */
+	ret2 = mxt_handle_messages(data, true);
+	if (ret2) {
+		dev_err(dev, "Error clearing msg buffer (%d)\n", ret2);
+		ret = ret2;
 	}
 
-out:
+	enable_irq(data->irq);
+free_cfg_copy:
+	kfree(cfg_copy);
+err_alloc_copy:
 	release_firmware(fw);
+	return ret;
+}
 
-	/* Change to slave address of application */
-	if (client->addr == MXT_BOOT_LOW)
-		client->addr = MXT_APP_LOW;
-	else
-		client->addr = MXT_APP_HIGH;
+/*
+ * Helper function for performing a T6 diagnostic command
+ */
+static int mxt_T6_diag_cmd(struct mxt_data *data, struct mxt_object *T6,
+			   u8 cmd)
+{
+	int ret;
+	u16 addr = T6->start_address + MXT_COMMAND_DIAGNOSTIC;
 
-	return ret;
+	ret = mxt_write_reg(data->client, addr, cmd);
+	if (ret)
+		return ret;
+
+	/*
+	 * Poll T6.diag until it returns 0x00, which indicates command has
+	 * completed.
+	 */
+	while (cmd != 0) {
+		ret = __mxt_read_reg(data->client, addr, 1, &cmd);
+		if (ret)
+			return ret;
+	}
+	return 0;
 }
 
-static ssize_t mxt_update_fw_store(struct device *dev,
-					struct device_attribute *attr,
-					const char *buf, size_t count)
+/*
+ * SysFS Helper function for reading DELTAS and REFERENCE values for T37 object
+ *
+ * For both modes, a T37_buf is allocated to stores matrix_xsize * matrix_ysize
+ * 2-byte (little-endian) values, which are returned to userspace unmodified.
+ *
+ * It is left to userspace to parse the 2-byte values.
+ * - deltas are signed 2's complement 2-byte little-endian values.
+ *     s32 delta = (b[0] + (b[1] << 8));
+ * - refs are signed 'offset binary' 2-byte little-endian values, with offset
+ *   value 0x4000:
+ *     s32 ref = (b[0] + (b[1] << 8)) - 0x4000;
+ */
+static ssize_t mxt_T37_fetch(struct mxt_data *data, u8 mode)
 {
-	struct mxt_data *data = dev_get_drvdata(dev);
-	int error;
+	struct mxt_object *T6, *T37;
+	u8 *obuf;
+	ssize_t ret = 0;
+	size_t i;
+	size_t T37_buf_size, num_pages;
+	size_t pos;
+
+	if (!data || !data->object_table)
+		return -ENODEV;
+
+	T6 = mxt_get_object(data, MXT_GEN_COMMAND_T6);
+	T37 = mxt_get_object(data, MXT_DEBUG_DIAGNOSTIC_T37);
+	if (!T6 || mxt_obj_size(T6) < 6 || !T37 || mxt_obj_size(T37) < 3) {
+		dev_err(&data->client->dev, "Invalid T6 or T37 object\n");
+		return -ENODEV;
+	}
+
+	/* Something has gone wrong if T37_buf is already allocated */
+	if (data->T37_buf)
+		return -EINVAL;
+
+	T37_buf_size = data->info.matrix_xsize * data->info.matrix_ysize *
+		       sizeof(__le16);
+	data->T37_buf_size = T37_buf_size;
+	data->T37_buf = kmalloc(data->T37_buf_size, GFP_KERNEL);
+	if (!data->T37_buf)
+		return -ENOMEM;
+
+	/* Temporary buffer used to fetch one T37 page */
+	obuf = kmalloc(mxt_obj_size(T37), GFP_KERNEL);
+	if (!obuf)
+		return -ENOMEM;
 
 	disable_irq(data->irq);
+	num_pages = DIV_ROUND_UP(T37_buf_size, mxt_obj_size(T37) - 2);
+	pos = 0;
+	for (i = 0; i < num_pages; i++) {
+		u8 cmd;
+		size_t chunk_len;
+
+		/* For first page, send mode as cmd, otherwise PageUp */
+		cmd = (i == 0) ? mode : MXT_T6_CMD_PAGE_UP;
+		ret = mxt_T6_diag_cmd(data, T6, cmd);
+		if (ret)
+			goto err_free_T37_buf;
 
-	error = mxt_load_fw(dev, MXT_FW_NAME);
-	if (error) {
-		dev_err(dev, "The firmware update failed(%d)\n", error);
-		count = error;
-	} else {
-		dev_dbg(dev, "The firmware update succeeded\n");
+		ret = __mxt_read_reg(data->client, T37->start_address,
+				mxt_obj_size(T37), obuf);
+		if (ret)
+			goto err_free_T37_buf;
 
-		/* Wait for reset */
-		msleep(MXT_FWRESET_TIME);
+		/* Verify first two bytes are current mode and page # */
+		if (obuf[0] != mode) {
+			dev_err(&data->client->dev,
+				"Unexpected mode (%u != %u)\n", obuf[0], mode);
+			ret = -EIO;
+			goto err_free_T37_buf;
+		}
 
-		mxt_free_object_table(data);
+		if (obuf[1] != i) {
+			dev_err(&data->client->dev,
+				"Unexpected page (%u != %zu)\n", obuf[1], i);
+			ret = -EIO;
+			goto err_free_T37_buf;
+		}
 
-		mxt_initialize(data);
+		/*
+		 * Copy the data portion of the page, or however many bytes are
+		 * left, whichever is less.
+		 */
+		chunk_len = min(mxt_obj_size(T37) - 2, T37_buf_size - pos);
+		memcpy(&data->T37_buf[pos], &obuf[2], chunk_len);
+		pos += chunk_len;
 	}
 
+	goto out;
+
+err_free_T37_buf:
+	kfree(data->T37_buf);
+	data->T37_buf = NULL;
+	data->T37_buf_size = 0;
+out:
+	kfree(obuf);
 	enable_irq(data->irq);
+	return ret ?: 0;
+}
 
-	error = mxt_make_highchg(data);
-	if (error)
-		return error;
+static int mxt_update_file_name(struct device *dev, char** file_name,
+				const char *buf, size_t count)
+{
+	char *file_name_tmp;
 
-	return count;
-}
+	/* Simple sanity check */
+	if (count > 64) {
+		dev_warn(dev, "File name too long\n");
+		return -EINVAL;
+	}
 
-static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
-static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
-static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
-static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
+	file_name_tmp = krealloc(*file_name, count + 1, GFP_KERNEL);
+	if (!file_name_tmp) {
+		dev_warn(dev, "no memory\n");
+		return -ENOMEM;
+	}
 
-static struct attribute *mxt_attrs[] = {
-	&dev_attr_fw_version.attr,
-	&dev_attr_hw_version.attr,
+	*file_name = file_name_tmp;
+	memcpy(*file_name, buf, count);
+
+	/* Echo into the sysfs entry may append newline at the end of buf */
+	if (buf[count - 1] == '\n')
+		(*file_name)[count - 1] = '\0';
+	else
+		(*file_name)[count] = '\0';
+
+	return 0;
+}
+
+static ssize_t mxt_backupnv_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int ret;
+
+	/* Backup non-volatile memory */
+	ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+			       MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
+	if (ret)
+		return ret;
+	msleep(MXT_BACKUP_TIME);
+
+	return count;
+}
+
+static ssize_t mxt_calibrate_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int ret;
+
+	disable_irq(data->irq);
+
+	/* Perform touch surface recalibration */
+	ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+			MXT_COMMAND_CALIBRATE, 1);
+	if (ret)
+		goto out;
+	msleep(MXT_CAL_TIME);
+
+out:
+	enable_irq(data->irq);
+	return ret ?: count;
+}
+
+static ssize_t mxt_config_csum_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	return scnprintf(buf, PAGE_SIZE, "%06x\n", data->config_csum);
+}
+
+static ssize_t mxt_config_file_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", data->config_file);
+}
+
+static ssize_t mxt_config_file_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int ret;
+
+	ret = mxt_update_file_name(dev, &data->config_file, buf, count);
+	return ret ? ret : count;
+}
+
+static ssize_t mxt_fw_file_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", data->fw_file);
+}
+
+static ssize_t mxt_fw_file_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int ret;
+
+	ret = mxt_update_file_name(dev, &data->fw_file, buf, count);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+/* Firmware Version is returned as Major.Minor.Build */
+static ssize_t mxt_fw_version_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	struct mxt_info *info = &data->info;
+	return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n",
+			 info->version >> 4, info->version & 0xf, info->build);
+}
+
+/* Hardware Version is returned as FamilyID.VariantID */
+static ssize_t mxt_hw_version_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	struct mxt_info *info = &data->info;
+	return scnprintf(buf, PAGE_SIZE, "%u.%u\n",
+			 info->family_id, info->variant_id);
+}
+
+static ssize_t mxt_info_csum_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	return scnprintf(buf, PAGE_SIZE, "%06x\n", data->info_csum);
+}
+
+/* Matrix Size is <MatrixSizeX> <MatrixSizeY> */
+static ssize_t mxt_matrix_size_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	struct mxt_info *info = &data->info;
+	return scnprintf(buf, PAGE_SIZE, "%u %u\n",
+			 info->matrix_xsize, info->matrix_ysize);
+}
+
+static ssize_t mxt_object_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int ret;
+	u32 param;
+	u8 type, instance, offset, val;
+
+	ret = kstrtou32(buf, 16, &param);
+	if (ret < 0)
+		return -EINVAL;
+
+	/*
+	 * Byte Write Command is encoded in 32-bit word: TTIIOOVV:
+	 * <Type> <Instance> <Offset> <Value>
+	 */
+	type = (param & 0xff000000) >> 24;
+	instance = (param & 0x00ff0000) >> 16;
+	offset = (param & 0x0000ff00) >> 8;
+	val = param & 0x000000ff;
+
+	ret = mxt_write_obj_instance(data, type, instance, offset, val);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static ssize_t mxt_update_config_store(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	ssize_t ret;
+
+	ret = mxt_load_config(data, data->config_file);
+	if (ret)
+		dev_err(dev, "The config update failed (%zd)\n", ret);
+	else
+		dev_dbg(dev, "The config update succeeded\n");
+
+	return ret ?: count;
+}
+
+static int mxt_load_fw(struct device *dev, const char *fn)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	const struct firmware *fw = NULL;
+	unsigned int frame_size;
+	unsigned int pos = 0;
+	int ret;
+
+	ret = request_firmware(&fw, fn, dev);
+	if (ret) {
+		dev_err(dev, "Unable to open firmware %s\n", fn);
+		return ret;
+	}
+
+	ret = mxt_enter_bl(data);
+	if (ret) {
+		dev_err(dev, "Failed to reset to bootloader.\n");
+		goto out;
+	}
+
+	ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD);
+	if (ret)
+		goto out;
+
+	/* Unlock bootloader */
+	ret = mxt_unlock_bootloader(client);
+	if (ret)
+		goto out;
+
+	while (pos < fw->size) {
+		ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA);
+		if (ret)
+			goto out;
+
+		frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
+
+		/* We should add 2 at frame size as the the firmware data is not
+		 * included the CRC bytes.
+		 */
+		frame_size += 2;
+
+		/* Write one frame to device */
+		ret = mxt_fw_write(client, fw->data + pos, frame_size);
+		if (ret)
+			goto out;
+
+		ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS);
+		if (ret)
+			goto out;
+
+		pos += frame_size;
+
+		dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
+	}
+
+	/* Device exits bl mode to app mode only if successful */
+	mxt_exit_bl(data);
+out:
+	release_firmware(fw);
+
+	return ret;
+}
+
+static ssize_t mxt_update_fw_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int error;
+
+	error = mxt_load_fw(dev, data->fw_file);
+	if (error) {
+		dev_err(dev, "The firmware update failed(%d)\n", error);
+		count = error;
+	} else {
+		dev_dbg(dev, "The firmware update succeeded\n");
+	}
+
+	return count;
+}
+
+static ssize_t mxt_suspend_acq_interval_ms_show(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	u8 interval_reg = data->suspend_acq_interval;
+	u8 interval_ms = (interval_reg == 255) ? 0 : interval_reg;
+	return scnprintf(buf, PAGE_SIZE, "%u\n", interval_ms);
+}
+
+static ssize_t mxt_suspend_acq_interval_ms_store(struct device *dev,
+						 struct device_attribute *attr,
+						 const char *buf, size_t count)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int ret;
+	u32 param;
+
+	ret = kstrtou32(buf, 10, &param);
+	if (ret < 0)
+		return -EINVAL;
+
+	/* 0 ms inteval means "free run" */
+	if (param == 0)
+		param = 255;
+	/* 254 ms is the largest interval */
+	else if (param > 254)
+		param = 254;
+
+	data->suspend_acq_interval = param;
+	return count;
+}
+
+static DEVICE_ATTR(backupnv, S_IWUSR, NULL, mxt_backupnv_store);
+static DEVICE_ATTR(calibrate, S_IWUSR, NULL, mxt_calibrate_store);
+static DEVICE_ATTR(config_csum, S_IRUGO, mxt_config_csum_show, NULL);
+static DEVICE_ATTR(config_file, S_IRUGO | S_IWUSR, mxt_config_file_show,
+		   mxt_config_file_store);
+static DEVICE_ATTR(fw_file, S_IRUGO | S_IWUSR, mxt_fw_file_show,
+		   mxt_fw_file_store);
+static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
+static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
+static DEVICE_ATTR(info_csum, S_IRUGO, mxt_info_csum_show, NULL);
+static DEVICE_ATTR(matrix_size, S_IRUGO, mxt_matrix_size_show, NULL);
+static DEVICE_ATTR(object, S_IWUSR, NULL, mxt_object_store);
+static DEVICE_ATTR(update_config, S_IWUSR, NULL, mxt_update_config_store);
+static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
+static DEVICE_ATTR(suspend_acq_interval_ms, S_IRUGO | S_IWUSR,
+		   mxt_suspend_acq_interval_ms_show,
+		   mxt_suspend_acq_interval_ms_store);
+
+static struct attribute *mxt_attrs[] = {
+	&dev_attr_backupnv.attr,
+	&dev_attr_calibrate.attr,
+	&dev_attr_config_csum.attr,
+	&dev_attr_config_file.attr,
+	&dev_attr_fw_file.attr,
+	&dev_attr_fw_version.attr,
+	&dev_attr_hw_version.attr,
+	&dev_attr_info_csum.attr,
+	&dev_attr_matrix_size.attr,
 	&dev_attr_object.attr,
+	&dev_attr_update_config.attr,
 	&dev_attr_update_fw.attr,
 	NULL
 };
 
-static const struct attribute_group mxt_attr_group = {
-	.attrs = mxt_attrs,
+static const struct attribute_group mxt_attr_group = {
+	.attrs = mxt_attrs,
+};
+
+static struct attribute *mxt_power_attrs[] = {
+	&dev_attr_suspend_acq_interval_ms.attr,
+	NULL
+};
+
+static const struct attribute_group mxt_power_attr_group = {
+	.name = power_group_name,
+	.attrs = mxt_power_attrs,
+};
+
+/*
+ **************************************************************
+ * debugfs helper functions
+ **************************************************************
+*/
+
+/*
+ * Print the formatted string into the end of string |*str| which has size
+ * |*str_size|. Extra space will be allocated to hold the formatted string
+ * and |*str_size| will be updated accordingly.
+ */
+static int mxt_asprintf(char **str, size_t *str_size, const char *fmt, ...)
+{
+	unsigned int len;
+	va_list ap, aq;
+	int ret;
+	char *str_tmp;
+
+	va_start(ap, fmt);
+	va_copy(aq, ap);
+	len = vsnprintf(NULL, 0, fmt, aq);
+	va_end(aq);
+
+	str_tmp = krealloc(*str, *str_size + len + 1, GFP_KERNEL);
+	if (str_tmp == NULL)
+		return -ENOMEM;
+
+	*str = str_tmp;
+
+	ret = vsnprintf(*str + *str_size, len + 1, fmt, ap);
+	va_end(ap);
+
+	if (ret != len)
+		return -EINVAL;
+
+	*str_size += len;
+
+	return 0;
+}
+
+static int mxt_instance_fetch(char **str, size_t *count,
+		struct mxt_object *object, int instance, const u8 *val)
+{
+	int i;
+	int ret;
+
+	if (mxt_obj_instances(object) > 1) {
+		ret = mxt_asprintf(str, count, "Instance: %zu\n", instance);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < mxt_obj_size(object); i++) {
+		ret = mxt_asprintf(str, count,
+				"\t[%2zu]: %02x (%d)\n", i, val[i], val[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mxt_object_fetch(struct mxt_data *data)
+{
+	struct mxt_object *object;
+	size_t count = 0;
+	size_t i, j;
+	int ret = 0;
+	char *str = NULL;
+	u8 *obuf;
+
+	if (data->object_str)
+		return -EINVAL;
+
+	/* Pre-allocate buffer large enough to hold max sized object. */
+	obuf = kmalloc(256, GFP_KERNEL);
+	if (!obuf)
+		return -ENOMEM;
+
+	for (i = 0; i < data->info.object_num; i++) {
+		object = data->object_table + i;
+
+		if (!mxt_object_readable(object->type))
+			continue;
+
+		ret = mxt_asprintf(&str, &count, "\nT%u\n", object->type);
+		if (ret)
+			goto err;
+
+		for (j = 0; j < mxt_obj_instances(object); j++) {
+			u16 size = mxt_obj_size(object);
+			u16 addr = object->start_address + j * size;
+
+			ret = __mxt_read_reg(data->client, addr, size, obuf);
+			if (ret)
+				goto done;
+
+			ret = mxt_instance_fetch(&str, &count, object, j, obuf);
+			if (ret)
+				goto err;
+		}
+	}
+
+	goto done;
+
+err:
+	kfree(str);
+	str = NULL;
+	count = 0;
+done:
+	data->object_str = str;
+	data->object_str_size = count;
+	kfree(obuf);
+	return ret;
+}
+
+/*
+ **************************************************************
+ * debugfs interface
+ **************************************************************
+*/
+static int mxt_debugfs_T37_open(struct inode *inode, struct file *file)
+{
+	struct mxt_data *mxt = inode->i_private;
+	int ret;
+	u8 cmd;
+
+	if (file->f_dentry == mxt->dentry_deltas)
+		cmd = MXT_T6_CMD_DELTAS;
+	else if (file->f_dentry == mxt->dentry_refs)
+		cmd = MXT_T6_CMD_REFS;
+	else
+		return -EINVAL;
+
+	/* Only allow one T37 debugfs file to be opened at a time */
+	ret = mutex_lock_interruptible(&mxt->T37_buf_mutex);
+	if (ret)
+		return ret;
+
+	if (!i2c_use_client(mxt->client)) {
+		ret = -ENODEV;
+		goto err_unlock;
+	}
+
+	/* Fetch all T37 pages into mxt->T37_buf */
+	ret = mxt_T37_fetch(mxt, cmd);
+	if (ret)
+		goto err_release;
+
+	file->private_data = mxt;
+
+	return 0;
+
+err_release:
+	i2c_release_client(mxt->client);
+err_unlock:
+	mutex_unlock(&mxt->T37_buf_mutex);
+	return ret;
+}
+
+static int mxt_debugfs_T37_release(struct inode *inode, struct file *file)
+{
+	struct mxt_data *mxt = file->private_data;
+
+	file->private_data = NULL;
+
+	kfree(mxt->T37_buf);
+	mxt->T37_buf = NULL;
+	mxt->T37_buf_size = 0;
+
+	i2c_release_client(mxt->client);
+	mutex_unlock(&mxt->T37_buf_mutex);
+
+	return 0;
+}
+
+
+/* Return some bytes from the buffered T37 object, starting from *ppos */
+static ssize_t mxt_debugfs_T37_read(struct file *file, char __user *buffer,
+				    size_t count, loff_t *ppos)
+{
+	struct mxt_data *mxt = file->private_data;
+
+	if (!mxt->T37_buf)
+		return -ENODEV;
+
+	if (*ppos >= mxt->T37_buf_size)
+		return 0;
+
+	if (count + *ppos > mxt->T37_buf_size)
+		count = mxt->T37_buf_size - *ppos;
+
+	if (copy_to_user(buffer, &mxt->T37_buf[*ppos], count))
+		return -EFAULT;
+
+	*ppos += count;
+
+	return count;
+}
+
+static const struct file_operations mxt_debugfs_T37_fops = {
+	.owner = THIS_MODULE,
+	.open = mxt_debugfs_T37_open,
+	.release = mxt_debugfs_T37_release,
+	.read = mxt_debugfs_T37_read
+};
+
+static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
+{
+	struct mxt_data *mxt = inode->i_private;
+	int ret;
+
+	/* Only allow one object debugfs file to be opened at a time */
+	ret = mutex_lock_interruptible(&mxt->object_str_mutex);
+	if (ret)
+		return ret;
+
+	if (!i2c_use_client(mxt->client)) {
+		ret = -ENODEV;
+		goto err_object_unlock;
+	}
+
+	ret = mxt_object_fetch(mxt);
+	if (ret)
+		goto err_object_i2c_release;
+	file->private_data = mxt;
+
+	return 0;
+
+err_object_i2c_release:
+	i2c_release_client(mxt->client);
+err_object_unlock:
+	mutex_unlock(&mxt->object_str_mutex);
+	return ret;
+}
+
+static int mxt_debugfs_object_release(struct inode *inode, struct file *file)
+{
+	struct mxt_data *mxt = file->private_data;
+	file->private_data = NULL;
+
+	kfree(mxt->object_str);
+	mxt->object_str = NULL;
+	mxt->object_str_size = 0;
+
+	i2c_release_client(mxt->client);
+	mutex_unlock(&mxt->object_str_mutex);
+
+	return 0;
+}
+
+static ssize_t mxt_debugfs_object_read(struct file *file, char __user* buffer,
+				   size_t count, loff_t *ppos)
+{
+	struct mxt_data *mxt = file->private_data;
+	if (!mxt->object_str)
+		return -ENODEV;
+
+	if (*ppos >= mxt->object_str_size)
+		return 0;
+
+	if (count + *ppos > mxt->object_str_size)
+		count = mxt->object_str_size - *ppos;
+
+	if (copy_to_user(buffer, &mxt->object_str[*ppos], count))
+		return -EFAULT;
+
+	*ppos += count;
+
+	return count;
+}
+
+static const struct file_operations mxt_debugfs_object_fops = {
+	.owner = THIS_MODULE,
+	.open = mxt_debugfs_object_open,
+	.release = mxt_debugfs_object_release,
+	.read = mxt_debugfs_object_read,
 };
 
+static int mxt_debugfs_init(struct mxt_data *mxt)
+{
+	struct device *dev = &mxt->client->dev;
+
+	if (!mxt_debugfs_root)
+		return -ENODEV;
+
+	mxt->dentry_dev = debugfs_create_dir(kobject_name(&dev->kobj),
+					     mxt_debugfs_root);
+
+	if (!mxt->dentry_dev)
+		return -ENODEV;
+
+	mutex_init(&mxt->T37_buf_mutex);
+
+	mxt->dentry_deltas = debugfs_create_file("deltas", S_IRUSR,
+						 mxt->dentry_dev, mxt,
+						 &mxt_debugfs_T37_fops);
+	mxt->dentry_refs = debugfs_create_file("refs", S_IRUSR,
+					       mxt->dentry_dev, mxt,
+					       &mxt_debugfs_T37_fops);
+	mutex_init(&mxt->object_str_mutex);
+
+	mxt->dentry_object = debugfs_create_file("object", S_IRUGO,
+						 mxt->dentry_dev, mxt,
+						 &mxt_debugfs_object_fops);
+	return 0;
+}
+
+static void mxt_debugfs_remove(struct mxt_data *mxt)
+{
+	if (mxt->dentry_dev) {
+		debugfs_remove_recursive(mxt->dentry_dev);
+		mutex_destroy(&mxt->object_str_mutex);
+		kfree(mxt->object_str);
+		mutex_destroy(&mxt->T37_buf_mutex);
+		kfree(mxt->T37_buf);
+	}
+}
+
+static int mxt_save_regs(struct mxt_data *data, u8 type, u8 instance,
+			 u8 offset, u8 *val, u16 size)
+{
+	struct mxt_object *object;
+	u16 addr;
+	int ret;
+
+	object = mxt_get_object(data, type);
+	if (!object)
+		return -EINVAL;
+
+	addr = object->start_address + instance * mxt_obj_size(object) + offset;
+	ret = __mxt_read_reg(data->client, addr, size, val);
+	if (ret)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int mxt_set_regs(struct mxt_data *data, u8 type, u8 instance,
+			u8 offset, const u8 *val, u16 size)
+{
+	struct mxt_object *object;
+	u16 addr;
+	int ret;
+
+	object = mxt_get_object(data, type);
+	if (!object)
+		return -EINVAL;
+
+	addr = object->start_address + instance * mxt_obj_size(object) + offset;
+	ret = __mxt_write_reg(data->client, addr, size, val);
+	if (ret)
+		return -EINVAL;
+
+	return 0;
+}
+
 static void mxt_start(struct mxt_data *data)
 {
-	/* Touch enable */
-	mxt_write_object(data,
-			MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83);
+	/* Enable touch reporting */
+	mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
+			 MXT_TOUCH_CTRL_OPERATIONAL);
 }
 
 static void mxt_stop(struct mxt_data *data)
 {
-	/* Touch disable */
-	mxt_write_object(data,
-			MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
+	/* Disable touch reporting */
+	mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
+			 MXT_TOUCH_CTRL_OFF);
 }
 
 static int mxt_input_open(struct input_dev *dev)
@@ -1095,51 +2612,60 @@ static void mxt_input_close(struct input_dev *dev)
 	mxt_stop(data);
 }
 
-static int mxt_probe(struct i2c_client *client,
-		const struct i2c_device_id *id)
+#if defined(CONFIG_ACPI_BUTTON)
+static int mxt_lid_notify(struct notifier_block *nb, unsigned long val,
+			   void *unused)
+{
+	struct mxt_data *data = container_of(nb, struct mxt_data, lid_notifier);
+
+	if (mxt_in_bootloader(data))
+		return NOTIFY_OK;
+
+	if (val == 0)
+		mxt_stop(data);
+	else
+		mxt_start(data);
+
+	return NOTIFY_OK;
+}
+#endif
+
+static int mxt_input_dev_create(struct mxt_data *data)
 {
-	const struct mxt_platform_data *pdata = client->dev.platform_data;
-	struct mxt_data *data;
 	struct input_dev *input_dev;
 	int error;
 	unsigned int num_mt_slots;
+	int max_area_channels;
+	int max_touch_major;
 
-	if (!pdata)
-		return -EINVAL;
-
-	data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!data || !input_dev) {
-		dev_err(&client->dev, "Failed to allocate memory\n");
-		error = -ENOMEM;
-		goto err_free_mem;
-	}
+	data->input_dev = input_dev = input_allocate_device();
+	if (!input_dev)
+		return -ENOMEM;
 
-	input_dev->name = "Atmel maXTouch Touchscreen";
-	snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
-		 client->adapter->nr, client->addr);
+	input_dev->name = (data->is_tp) ? "Atmel maXTouch Touchpad" :
+					  "Atmel maXTouch Touchscreen";
 	input_dev->phys = data->phys;
-
 	input_dev->id.bustype = BUS_I2C;
-	input_dev->dev.parent = &client->dev;
+	input_dev->dev.parent = &data->client->dev;
 	input_dev->open = mxt_input_open;
 	input_dev->close = mxt_input_close;
 
-	data->client = client;
-	data->input_dev = input_dev;
-	data->pdata = pdata;
-	data->irq = client->irq;
-
-	mxt_calc_resolution(data);
-
-	error = mxt_initialize(data);
-	if (error)
-		goto err_free_mem;
-
 	__set_bit(EV_ABS, input_dev->evbit);
 	__set_bit(EV_KEY, input_dev->evbit);
 	__set_bit(BTN_TOUCH, input_dev->keybit);
 
+	if (data->is_tp) {
+		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+		__set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
+
+		__set_bit(BTN_LEFT, input_dev->keybit);
+		__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+		__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
+		__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
+		__set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
+		__set_bit(BTN_TOOL_QUINTTAP, input_dev->keybit);
+	}
+
 	/* For single touch */
 	input_set_abs_params(input_dev, ABS_X,
 			     0, data->max_x, 0, 0);
@@ -1147,55 +2673,171 @@ static int mxt_probe(struct i2c_client *client,
 			     0, data->max_y, 0, 0);
 	input_set_abs_params(input_dev, ABS_PRESSURE,
 			     0, 255, 0, 0);
+	input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM);
+	input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM);
 
 	/* For multi touch */
 	num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
 	error = input_mt_init_slots(input_dev, num_mt_slots, 0);
 	if (error)
-		goto err_free_object;
+		goto err_free_device;
+
+	max_area_channels = min(255U, data->max_area_channels);
+	max_touch_major = get_touch_major_pixels(data, max_area_channels);
 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
-			     0, MXT_MAX_AREA, 0, 0);
+			     0, max_touch_major, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
 			     0, data->max_x, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
 			     0, data->max_y, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_PRESSURE,
 			     0, 255, 0, 0);
+	input_abs_set_res(input_dev, ABS_MT_POSITION_X, MXT_PIXELS_PER_MM);
+	input_abs_set_res(input_dev, ABS_MT_POSITION_Y, MXT_PIXELS_PER_MM);
 
 	input_set_drvdata(input_dev, data);
-	i2c_set_clientdata(client, data);
 
+	error = input_register_device(input_dev);
+	if (error)
+		goto err_free_device;
+
+	return 0;
+
+err_free_device:
+	input_free_device(data->input_dev);
+	data->input_dev = NULL;
+	return error;
+}
+
+static void mxt_initialize_async(void *closure, async_cookie_t cookie)
+{
+	struct mxt_data *data = closure;
+	struct i2c_client *client = data->client;
+	unsigned long irqflags;
+	int error;
+
+	if (mxt_in_bootloader(data)) {
+		dev_info(&client->dev, "device in bootloader at probe\n");
+	} else {
+		error = mxt_initialize(data);
+		if (error)
+			goto error_free_mem;
+
+		error = mxt_input_dev_create(data);
+		if (error)
+			goto error_free_object;
+	}
+
+	/* Default to falling edge if no platform data provided */
+	irqflags = data->pdata ? data->pdata->irqflags : IRQF_TRIGGER_FALLING;
 	error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
-				     pdata->irqflags | IRQF_ONESHOT,
+				     irqflags | IRQF_ONESHOT,
 				     client->name, data);
 	if (error) {
 		dev_err(&client->dev, "Failed to register interrupt\n");
-		goto err_free_object;
+		if (mxt_in_bootloader(data))
+			goto error_free_mem;
+		else
+			goto error_unregister_device;
 	}
 
-	error = mxt_make_highchg(data);
-	if (error)
-		goto err_free_irq;
+	if (!mxt_in_bootloader(data)) {
+		error = mxt_handle_messages(data, true);
+		if (error)
+			goto error_free_irq;
+	}
 
-	error = input_register_device(input_dev);
+	/* Force the device to report back status so we can cache the device
+	 * config checksum
+	 */
+	error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+				 MXT_COMMAND_REPORTALL, 1);
 	if (error)
-		goto err_free_irq;
+		dev_warn(&client->dev, "error making device report status.\n");
 
 	error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
+	if (error) {
+		dev_err(&client->dev, "error creating sysfs entries.\n");
+		goto error_free_irq;
+	}
+
+	error = sysfs_merge_group(&client->dev.kobj, &mxt_power_attr_group);
 	if (error)
-		goto err_unregister_device;
+		dev_warn(&client->dev, "error merging power sysfs entries.\n");
 
-	return 0;
+	error = mxt_debugfs_init(data);
+	if (error)
+		dev_warn(&client->dev, "error creating debugfs entries.\n");
+
+	return;
 
-err_unregister_device:
-	input_unregister_device(input_dev);
-	input_dev = NULL;
-err_free_irq:
+error_free_irq:
 	free_irq(client->irq, data);
-err_free_object:
+error_unregister_device:
+	input_unregister_device(data->input_dev);
+error_free_object:
 	kfree(data->object_table);
+error_free_mem:
+	kfree(data->fw_file);
+	kfree(data->config_file);
+	kfree(data);
+}
+
+static int mxt_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	const struct mxt_platform_data *pdata = client->dev.platform_data;
+	struct mxt_data *data;
+	int error;
+
+	data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
+	if (!data) {
+		dev_err(&client->dev, "Failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	data->is_tp = !strcmp(id->name, "atmel_mxt_tp");
+	snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
+		 client->adapter->nr, client->addr);
+
+	data->client = client;
+	i2c_set_clientdata(client, data);
+
+	data->pdata = pdata;
+	data->irq = client->irq;
+
+	init_completion(&data->bl_completion);
+	init_completion(&data->auto_cal_completion);
+
+	data->suspend_acq_interval = MXT_SUSPEND_ACQINT_VALUE;
+
+	error = mxt_update_file_name(&client->dev, &data->fw_file, MXT_FW_NAME,
+				     strlen(MXT_FW_NAME));
+	if (error)
+		goto err_free_mem;
+
+	error = mxt_update_file_name(&client->dev, &data->config_file,
+				     MXT_CONFIG_NAME, strlen(MXT_CONFIG_NAME));
+	if (error)
+		goto err_free_fw_file;
+
+	device_set_wakeup_enable(&client->dev, false);
+
+	async_schedule(mxt_initialize_async, data);
+
+#if defined(CONFIG_ACPI_BUTTON)
+	data->lid_notifier.notifier_call = mxt_lid_notify;
+	if (acpi_lid_notifier_register(&data->lid_notifier)) {
+		pr_info("lid notifier registration failed\n");
+		data->lid_notifier.notifier_call = NULL;
+	}
+#endif
+
+	return 0;
+
+err_free_fw_file:
+	kfree(data->fw_file);
 err_free_mem:
-	input_free_device(input_dev);
 	kfree(data);
 	return error;
 }
@@ -1204,26 +2846,166 @@ static int mxt_remove(struct i2c_client *client)
 {
 	struct mxt_data *data = i2c_get_clientdata(client);
 
+	mxt_debugfs_remove(data);
+	sysfs_unmerge_group(&client->dev.kobj, &mxt_power_attr_group);
 	sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
 	free_irq(data->irq, data);
-	input_unregister_device(data->input_dev);
+	if (data->input_dev)
+		input_unregister_device(data->input_dev);
+#if defined(CONFIG_ACPI_BUTTON)
+	if (data->lid_notifier.notifier_call)
+		acpi_lid_notifier_unregister(&data->lid_notifier);
+#endif
 	kfree(data->object_table);
+	kfree(data->fw_file);
+	kfree(data->config_file);
 	kfree(data);
 
 	return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
+
+static void mxt_suspend_enable_T9(struct mxt_data *data)
+{
+	struct device *dev = &data->client->dev;
+	u8 T9_ctrl = MXT_TOUCH_CTRL_ENABLE | MXT_TOUCH_CTRL_RPTEN;
+	int ret;
+	unsigned long timeout = msecs_to_jiffies(350);
+	bool need_enable = false;
+	bool need_report = false;
+
+	dev_dbg(dev, "Current T9_Ctrl is %x\n", data->T9_ctrl);
+
+	need_enable = !(data->T9_ctrl & MXT_TOUCH_CTRL_ENABLE);
+	need_report = !(data->T9_ctrl & MXT_TOUCH_CTRL_RPTEN);
+
+	/* If already enabled and reporting, do nothing */
+	if (!need_enable && !need_report)
+		return;
+
+	/* If the ENABLE bit is toggled, there will be auto-calibration msg.
+	 * We will have to clear this msg before going into suspend otherwise
+	 * it will wake up the device immediately
+	 */
+	if (need_enable)
+		INIT_COMPLETION(data->auto_cal_completion);
+
+	/* Enable T9 object (ENABLE and REPORT) */
+	ret = mxt_set_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
+			   &T9_ctrl, 1);
+	if (ret) {
+		dev_err(dev, "Set T9 ctrl config failed, %d\n", ret);
+		return;
+	}
+
+	if (need_enable) {
+		ret = wait_for_completion_interruptible_timeout(
+			&data->auto_cal_completion, timeout);
+		if (ret <= 0)
+			dev_err(dev, "Wait for auto cal completion failed.\n");
+	}
+}
+
 static int mxt_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mxt_data *data = i2c_get_clientdata(client);
 	struct input_dev *input_dev = data->input_dev;
+	const u8 T7_config_idle[3] = {
+			data->suspend_acq_interval,
+			data->suspend_acq_interval,
+			0x00 };
+	static const u8 T7_config_deepsleep[3] = { 0x00, 0x00, 0x00 };
+	const u8 *power_config;
+	int ret;
+
+	if (mxt_in_bootloader(data))
+		return 0;
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
+	/* Save 3 bytes T7 Power config */
+	ret = mxt_save_regs(data, MXT_GEN_POWER_T7, 0, 0,
+			    data->T7_config, 3);
+	if (ret)
+		dev_err(dev, "Save T7 Power config failed, %d\n", ret);
+	data->T7_config_valid = (ret == 0);
+
+	/*
+	 * Set T7 to idle mode if we allow wakeup from touch, otherwise
+	 * put it into deepsleep mode.
+	 */
+	power_config = device_may_wakeup(dev) ? T7_config_idle
+					      : T7_config_deepsleep;
+
+	ret = mxt_set_regs(data, MXT_GEN_POWER_T7, 0, 0,
+			   power_config, 3);
+	if (ret)
+		dev_err(dev, "Set T7 Power config failed, %d\n", ret);
+
+	/* Save 1 byte T9 Ctrl config */
+	ret = mxt_save_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
+			    &data->T9_ctrl, 1);
+	if (ret)
+		dev_err(dev, "Save T9 ctrl config failed, %d\n", ret);
+	data->T9_ctrl_valid = (ret == 0);
+
+	/*
+	 *  For tpads, save T42 and T19 ctrl registers if may wakeup,
+	 *  enable large object suppression, and disable button wake.
+	 *  This will prevent a lid close from acting as a wake source.
+	 */
+	if (data->is_tp && device_may_wakeup(dev)) {
+		u8 T42_sleep = 0x01;
+		u8 T19_sleep = 0x00;
+
+		ret = mxt_save_regs(data, MXT_PROCI_TOUCHSUPPRESSION_T42, 0, 0,
+				    &data->T42_ctrl, 1);
+		if (ret)
+			dev_err(dev, "Save T42 ctrl config failed, %d\n", ret);
+		data->T42_ctrl_valid = (ret == 0);
+
+		ret = mxt_save_regs(data, MXT_SPT_GPIOPWM_T19, 0, 0,
+				    &data->T19_ctrl, 1);
+		if (ret)
+			dev_err(dev, "Save T19 ctrl config failed, %d\n", ret);
+		data->T19_ctrl_valid = (ret == 0);
+
+
+		/* Enable Large Object Suppression */
+		ret = mxt_set_regs(data, MXT_PROCI_TOUCHSUPPRESSION_T42, 0, 0,
+				   &T42_sleep, 1);
+		if (ret)
+			dev_err(dev, "Set T42 ctrl failed, %d\n", ret);
+
+		/* Disable Touchpad Button via GPIO */
+		ret = mxt_set_regs(data, MXT_SPT_GPIOPWM_T19, 0, 0,
+				   &T19_sleep, 1);
+		if (ret)
+			dev_err(dev, "Set T19 ctrl failed, %d\n", ret);
+
+	} else {
+		data->T42_ctrl_valid = data->T19_ctrl_valid = false;
+	}
+
+	if (device_may_wakeup(dev)) {
+		/*
+		 * If we allow wakeup from touch, we have to enable T9 so
+		 * that IRQ can be generated from touch
+		 */
+
+		/* Set proper T9 ENABLE & REPTN bits */
+		if (data->T9_ctrl_valid)
+			mxt_suspend_enable_T9(data);
+
+		/* Enable wake from IRQ */
+		data->irq_wake = (enable_irq_wake(data->irq) == 0);
+	} else if (input_dev->users) {
 		mxt_stop(data);
+	}
+
+	disable_irq(data->irq);
 
 	mutex_unlock(&input_dev->mutex);
 
@@ -1235,20 +3017,81 @@ static int mxt_resume(struct device *dev)
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mxt_data *data = i2c_get_clientdata(client);
 	struct input_dev *input_dev = data->input_dev;
+	int ret;
 
-	/* Soft reset */
-	mxt_write_object(data, MXT_GEN_COMMAND_T6,
-			MXT_COMMAND_RESET, 1);
+	if (mxt_in_bootloader(data))
+		return 0;
 
-	msleep(MXT_RESET_TIME);
+	/* Process any pending message so that CHG line can be de-asserted */
+	ret = mxt_handle_messages(data, false);
+	if (ret)
+		dev_err(dev, "Handling message fails upon resume, %d\n", ret);
+
+	mxt_release_all_fingers(data);
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users)
-		mxt_start(data);
+#if defined(CONFIG_ACPI_BUTTON)
+	ret = acpi_lid_open();
+	if (ret == 0) {
+		/* lid is closed. set T9_ctrl to non operational resume */
+		data->T9_ctrl = MXT_TOUCH_CTRL_OFF;
+		data->T9_ctrl_valid = true;
+	} else if (ret == 1) {
+		/* lid is open. Set to operational */
+		data->T9_ctrl = MXT_TOUCH_CTRL_OPERATIONAL;
+		data->T9_ctrl_valid = true;
+	}
+#endif
+
+	/* Restore the T9 Ctrl config to before-suspend value */
+	if (data->T9_ctrl_valid) {
+		ret = mxt_set_regs(data, MXT_TOUCH_MULTI_T9, 0, 0,
+				   &data->T9_ctrl, 1);
+		if (ret)
+			dev_err(dev, "Set T9 ctrl config failed, %d\n", ret);
+	}
+
+	/* Restore the T7 Power config to before-suspend value */
+	if (data->T7_config_valid) {
+		ret = mxt_set_regs(data, MXT_GEN_POWER_T7, 0, 0,
+				   data->T7_config, 3);
+		if (ret)
+			dev_err(dev, "Set T7 power config failed, %d\n", ret);
+	}
+
+	/* Restore the T42 ctrl to before-suspend value */
+	if (data->T42_ctrl_valid) {
+		ret = mxt_set_regs(data, MXT_PROCI_TOUCHSUPPRESSION_T42, 0, 0,
+				   &data->T42_ctrl, 1);
+		if (ret)
+			dev_err(dev, "Set T42 ctrl failed, %d\n", ret);
+	}
+
+	/* Restore the T19 ctrl to before-suspend value */
+	if (data->T19_ctrl_valid) {
+		ret = mxt_set_regs(data, MXT_SPT_GPIOPWM_T19, 0, 0,
+				   &data->T19_ctrl, 1);
+		if (ret)
+			dev_err(dev, "Set T19 ctrl failed, %d\n", ret);
+	}
+
+	if (!device_may_wakeup(dev)) {
+		/* Recalibration in case of environment change */
+		ret = mxt_write_object(data, MXT_GEN_COMMAND_T6,
+				       MXT_COMMAND_CALIBRATE, 1);
+		if (ret)
+			dev_err(dev, "Resume recalibration failed %d\n", ret);
+		msleep(MXT_CAL_TIME);
+	}
 
 	mutex_unlock(&input_dev->mutex);
 
+	enable_irq(data->irq);
+
+	if (device_may_wakeup(dev) && data->irq_wake)
+		disable_irq_wake(data->irq);
+
 	return 0;
 }
 #endif
@@ -1258,6 +3101,7 @@ static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume);
 static const struct i2c_device_id mxt_id[] = {
 	{ "qt602240_ts", 0 },
 	{ "atmel_mxt_ts", 0 },
+	{ "atmel_mxt_tp", 0 },
 	{ "mXT224", 0 },
 	{ }
 };
@@ -1274,7 +3118,26 @@ static struct i2c_driver mxt_driver = {
 	.id_table	= mxt_id,
 };
 
-module_i2c_driver(mxt_driver);
+static int __init mxt_init(void)
+{
+	/* Create a global debugfs root for all atmel_mxt_ts devices */
+	mxt_debugfs_root = debugfs_create_dir(mxt_driver.driver.name, NULL);
+	if (mxt_debugfs_root == ERR_PTR(-ENODEV))
+		mxt_debugfs_root = NULL;
+
+	return i2c_add_driver(&mxt_driver);
+}
+
+static void __exit mxt_exit(void)
+{
+	if (mxt_debugfs_root)
+		debugfs_remove_recursive(mxt_debugfs_root);
+
+	i2c_del_driver(&mxt_driver);
+}
+
+module_init(mxt_init);
+module_exit(mxt_exit);
 
 /* Module information */
 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 51e7b87..f498211 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -26,6 +26,8 @@
 #include <linux/io.h>
 #include <linux/input/ti_am335x_tsc.h>
 #include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
 
@@ -33,6 +35,13 @@
 #define SEQ_SETTLE		275
 #define MAX_12BIT		((1 << 12) - 1)
 
+static const int config_pins[] = {
+	STEPCONFIG_XPP,
+	STEPCONFIG_XNN,
+	STEPCONFIG_YPP,
+	STEPCONFIG_YNN,
+};
+
 struct titsc {
 	struct input_dev	*input;
 	struct ti_tscadc_dev	*mfd_tscadc;
@@ -40,7 +49,10 @@ struct titsc {
 	unsigned int		wires;
 	unsigned int		x_plate_resistance;
 	bool			pen_down;
-	int			steps_to_configure;
+	int			coordinate_readouts;
+	u32			config_inp[4];
+	u32			bit_xp, bit_xn, bit_yp, bit_yn;
+	u32			inp_xp, inp_xn, inp_yp, inp_yn;
 };
 
 static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
@@ -54,92 +66,153 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg,
 	writel(val, tsc->mfd_tscadc->tscadc_base + reg);
 }
 
+static int titsc_config_wires(struct titsc *ts_dev)
+{
+	u32 analog_line[4];
+	u32 wire_order[4];
+	int i, bit_cfg;
+
+	for (i = 0; i < 4; i++) {
+		/*
+		 * Get the order in which TSC wires are attached
+		 * w.r.t. each of the analog input lines on the EVM.
+		 */
+		analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4;
+		wire_order[i] = ts_dev->config_inp[i] & 0x0F;
+		if (WARN_ON(analog_line[i] > 7))
+			return -EINVAL;
+		if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins)))
+			return -EINVAL;
+	}
+
+	for (i = 0; i < 4; i++) {
+		int an_line;
+		int wi_order;
+
+		an_line = analog_line[i];
+		wi_order = wire_order[i];
+		bit_cfg = config_pins[wi_order];
+		if (bit_cfg == 0)
+			return -EINVAL;
+		switch (wi_order) {
+		case 0:
+			ts_dev->bit_xp = bit_cfg;
+			ts_dev->inp_xp = an_line;
+			break;
+
+		case 1:
+			ts_dev->bit_xn = bit_cfg;
+			ts_dev->inp_xn = an_line;
+			break;
+
+		case 2:
+			ts_dev->bit_yp = bit_cfg;
+			ts_dev->inp_yp = an_line;
+			break;
+		case 3:
+			ts_dev->bit_yn = bit_cfg;
+			ts_dev->inp_yn = an_line;
+			break;
+		}
+	}
+	return 0;
+}
+
 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;
+	int i;
+	int end_step;
+	u32 stepenable;
 
 	config = STEPCONFIG_MODE_HWSYNC |
-			STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
+			STEPCONFIG_AVG_16 | ts_dev->bit_xp;
 	switch (ts_dev->wires) {
 	case 4:
-		config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+		config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
 		break;
 	case 5:
-		config |= STEPCONFIG_YNN |
-				STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
-				STEPCONFIG_YPP;
+		config |= ts_dev->bit_yn |
+				STEPCONFIG_INP_AN4 | ts_dev->bit_xn |
+				ts_dev->bit_yp;
 		break;
 	case 8:
-		config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+		config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
 		break;
 	}
 
-	for (i = 1; i <= ts_dev->steps_to_configure; i++) {
+	/* 1 … coordinate_readouts is for X */
+	end_step = ts_dev->coordinate_readouts;
+	for (i = 0; i < end_step; 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;
+			STEPCONFIG_AVG_16 | ts_dev->bit_yn |
+			STEPCONFIG_INM_ADCREFM;
 	switch (ts_dev->wires) {
 	case 4:
-		config |= STEPCONFIG_YPP;
+		config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
 		break;
 	case 5:
-		config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
-				STEPCONFIG_XNP | STEPCONFIG_YPN;
+		config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
+				ts_dev->bit_xn | ts_dev->bit_yp;
 		break;
 	case 8:
-		config |= STEPCONFIG_YPP;
+		config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
 		break;
 	}
 
-	for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
+	/* coordinate_readouts … coordinate_readouts * 2 is for Y */
+	end_step = ts_dev->coordinate_readouts * 2;
+	for (i = ts_dev->coordinate_readouts; i < end_step; 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 |
+	config = ts_dev->bit_xp | ts_dev->bit_yn |
 			STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
-			STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
+			STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp);
 
 	titsc_writel(ts_dev, REG_CHARGECONFIG, config);
 	titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
 
-	config = 0;
-	/* Configure to calculate pressure */
+	/* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */
 	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_AVG_16 | ts_dev->bit_yp |
+			ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
+			STEPCONFIG_INP(ts_dev->inp_xp);
+	titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
+	titsc_writel(ts_dev, REG_STEPDELAY(end_step),
 			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),
+	end_step++;
+	config |= STEPCONFIG_INP(ts_dev->inp_yn);
+	titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
+	titsc_writel(ts_dev, REG_STEPDELAY(end_step),
 			STEPCONFIG_OPENDLY);
 
-	titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
+	/* The steps1 … end and bit 0 for TS_Charge */
+	stepenable = (1 << (end_step + 2)) - 1;
+	am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable);
 }
 
 static void titsc_read_coordinates(struct titsc *ts_dev,
-				    unsigned int *x, unsigned int *y)
+		u32 *x, u32 *y, u32 *z1, u32 *z2)
 {
 	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;
+	unsigned int creads = ts_dev->coordinate_readouts;
 
+	*z1 = *z2 = 0;
+	if (fifocount % (creads * 2 + 2))
+		fifocount -= fifocount % (creads * 2 + 2);
 	/*
 	 * Delta filter is used to remove large variations in sampled
 	 * values from ADC. The filter tries to predict where the next
@@ -148,32 +221,32 @@ static void titsc_read_coordinates(struct titsc *ts_dev,
 	 * 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++) {
+	for (i = 0; i < fifocount; 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;
+
+		channel = (read & 0xf0000) >> 16;
+		read &= 0xfff;
+		if (channel < creads) {
 			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;
+		} else if (channel < creads * 2) {
 			diff = abs(read - prev_val_y);
 			if (diff < prev_diff_y) {
 				prev_diff_y = diff;
 				*y = read;
 			}
 			prev_val_y = read;
+
+		} else if (channel < creads * 2 + 1) {
+			*z1 = read;
+
+		} else if (channel < creads * 2 + 2) {
+			*z2 = read;
 		}
 	}
 }
@@ -186,23 +259,19 @@ static irqreturn_t titsc_irq(int irq, void *dev)
 	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);
+       /*
+	* ADC and touchscreen share the IRQ line.
+	* FIFO1 threshold interrupt is used by ADC,
+	* hence return from touchscreen IRQ handler if FIFO1
+	* threshold interrupt occurred.
+	*/
+	if (status & IRQENB_FIFO1THRES)
+		return IRQ_NONE;
+	else if (status & IRQENB_FIFO0THRES) {
+
+		titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
 
 		if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
 			/*
@@ -210,10 +279,10 @@ static irqreturn_t titsc_irq(int irq, void *dev)
 			 * Resistance(touch) = x plate resistance *
 			 * x postion/4096 * ((z2 / z1) - 1)
 			 */
-			z = z2 - z1;
+			z = z1 - z2;
 			z *= x;
 			z *= ts_dev->x_plate_resistance;
-			z /= z1;
+			z /= z2;
 			z = (z + 2047) >> 12;
 
 			if (z <= MAX_12BIT) {
@@ -248,10 +317,71 @@ static irqreturn_t titsc_irq(int irq, void *dev)
 		irqclr |= IRQENB_PENUP;
 	}
 
-	titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
+	if (status & IRQENB_HW_PEN) {
 
-	titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
-	return IRQ_HANDLED;
+		titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00);
+		titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
+	}
+
+	if (irqclr) {
+		titsc_writel(ts_dev, REG_IRQSTATUS, (status | irqclr));
+		am335x_tsc_se_update(ts_dev->mfd_tscadc);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+static int titsc_parse_dt(struct ti_tscadc_dev *tscadc_dev,
+					struct titsc *ts_dev)
+{
+	struct device_node *node = tscadc_dev->dev->of_node;
+	int err;
+
+	if (!node)
+		return -EINVAL;
+	node = of_get_child_by_name(node, "tsc");
+	err = of_property_read_u32(node, "ti,wires", &ts_dev->wires);
+	if (err < 0)
+		return err;
+	switch (ts_dev->wires) {
+	case 4:
+	case 5:
+	case 8:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	err = of_property_read_u32(node, "ti,x-plate-resistance",
+			&ts_dev->x_plate_resistance);
+	if (err < 0)
+		return err;
+
+	err = of_property_read_u32(node, "ti,coordinate-readouts",
+			&ts_dev->coordinate_readouts);
+	if (err < 0)
+		return err;
+
+	return of_property_read_u32_array(node, "ti,wire-config",
+			ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp));
+}
+
+static int titsc_parse_pdata(struct ti_tscadc_dev *tscadc_dev,
+					struct titsc *ts_dev)
+{
+	struct mfd_tscadc_board	*pdata = tscadc_dev->dev->platform_data;
+
+	if (!pdata)
+		return -EINVAL;
+
+	ts_dev->wires = pdata->tsc_init->wires;
+	ts_dev->x_plate_resistance =
+		pdata->tsc_init->x_plate_resistance;
+	ts_dev->coordinate_readouts =
+		pdata->tsc_init->coordinate_readouts;
+	memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config,
+		sizeof(pdata->tsc_init->wire_config));
+	return 0;
 }
 
 /*
@@ -262,17 +392,9 @@ static int 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;
+	struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
 	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();
@@ -286,20 +408,33 @@ static int titsc_probe(struct platform_device *pdev)
 	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;
+
+	//if (tscadc_dev->dev->platform_data)
+	//	err = titsc_parse_pdata(tscadc_dev, ts_dev);
+	//else
+		err = titsc_parse_dt(tscadc_dev, ts_dev);
+
+	if (err) {
+		dev_err(&pdev->dev, "Could not find valid DT data.\n");
+		goto err_free_mem;
+	}
 
 	err = request_irq(ts_dev->irq, titsc_irq,
-			  0, pdev->dev.driver->name, ts_dev);
+			  IRQF_SHARED, pdev->dev.driver->name, ts_dev);
 	if (err) {
 		dev_err(&pdev->dev, "failed to allocate irq.\n");
 		goto err_free_mem;
 	}
 
 	titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
+	err = titsc_config_wires(ts_dev);
+	if (err) {
+		dev_err(&pdev->dev, "wrong i/p wire configuration\n");
+		goto err_free_irq;
+	}
 	titsc_step_config(ts_dev);
-	titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
+	titsc_writel(ts_dev, REG_FIFO0THR,
+			ts_dev->coordinate_readouts * 2 + 2 - 1);
 
 	input_dev->name = "ti-tsc";
 	input_dev->dev.parent = &pdev->dev;
@@ -329,11 +464,16 @@ err_free_mem:
 
 static int titsc_remove(struct platform_device *pdev)
 {
-	struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
-	struct titsc *ts_dev = tscadc_dev->tsc;
+	struct titsc *ts_dev = platform_get_drvdata(pdev);
+	u32 steps;
 
 	free_irq(ts_dev->irq, ts_dev);
 
+	/* total steps followed by the enable mask */
+	steps = 2 * ts_dev->coordinate_readouts + 2;
+	steps = (1 << steps) - 1;
+	am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps);
+
 	input_unregister_device(ts_dev->input);
 
 	platform_set_drvdata(pdev, NULL);
@@ -344,10 +484,11 @@ static int titsc_remove(struct platform_device *pdev)
 #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;
+	struct titsc *ts_dev = dev_get_drvdata(dev);
+	struct ti_tscadc_dev *tscadc_dev;
 	unsigned int idle;
 
+	tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
 	if (device_may_wakeup(tscadc_dev->dev)) {
 		idle = titsc_readl(ts_dev, REG_IRQENABLE);
 		titsc_writel(ts_dev, REG_IRQENABLE,
@@ -359,9 +500,10 @@ static int titsc_suspend(struct device *dev)
 
 static int titsc_resume(struct device *dev)
 {
-	struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
-	struct titsc *ts_dev = tscadc_dev->tsc;
+	struct titsc *ts_dev = dev_get_drvdata(dev);
+	struct ti_tscadc_dev *tscadc_dev;
 
+	tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
 	if (device_may_wakeup(tscadc_dev->dev)) {
 		titsc_writel(ts_dev, REG_IRQWAKEUP,
 				0x00);
@@ -369,7 +511,7 @@ static int titsc_resume(struct device *dev)
 	}
 	titsc_step_config(ts_dev);
 	titsc_writel(ts_dev, REG_FIFO0THR,
-			ts_dev->steps_to_configure);
+			ts_dev->coordinate_readouts * 2 + 2 - 1);
 	return 0;
 }
 
@@ -382,6 +524,12 @@ static const struct dev_pm_ops titsc_pm_ops = {
 #define TITSC_PM_OPS NULL
 #endif
 
+static const struct of_device_id ti_tsc_dt_ids[] = {
+	{ .compatible = "ti,ti-tscadc", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids);
+
 static struct platform_driver ti_tsc_driver = {
 	.probe	= titsc_probe,
 	.remove	= titsc_remove,
@@ -389,6 +537,7 @@ static struct platform_driver ti_tsc_driver = {
 		.name   = "tsc",
 		.owner	= THIS_MODULE,
 		.pm	= TITSC_PM_OPS,
+		.of_match_table = of_match_ptr(ti_tsc_dt_ids),
 	},
 };
 module_platform_driver(ti_tsc_driver);
diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c
index de7cd83..3154c1f 100644
--- a/drivers/media/i2c/soc_camera/mt9t112.c
+++ b/drivers/media/i2c/soc_camera/mt9t112.c
@@ -16,7 +16,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#define DEBUG
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -31,7 +31,9 @@
 #include <media/v4l2-common.h>
 
 /* you can check PLL/clock info */
-/* #define EXT_CLOCK 24000000 */
+#define EXT_CLOCK 32000000
+
+//#define TEST_PATTERN
 
 /************************************************************************
 			macro
@@ -67,6 +69,8 @@
 
 #define mt9t112_reg_read(ret, client, a) \
 	ECHECKER(ret, __mt9t112_reg_read(client, a))
+#define mt9t112_mcu_read(ret, client, a) \
+	ECHECKER(ret, __mt9t112_mcu_read(client, a))
 
 /*
  * Logical address
@@ -85,6 +89,33 @@ struct mt9t112_format {
 	u16 order;
 };
 
+struct mt9t112_resolution_param {
+	u16 col_strt;
+	u16 row_end;
+	u16 col_end;
+	u16 read_mode;
+	u16 fine_cor;
+	u16 fine_min;
+	u16 fine_max;
+	u16 base_lines;
+	u16 min_lin_len;
+	u16 line_len;
+	u16 con_width;
+	u16 con_height;
+	u16 s_f1_50;
+	u16 s_f2_50;
+	u16 s_f1_60;
+	u16 s_f2_60;
+	u16 per_50;
+	u16 per_50_M;
+	u16 per_60;
+	u16 fd_w_height;
+	u16 tx_water;
+	u16 max_fd_50;
+	u16 max_fd_60;
+	u16 targ_fd;
+};
+
 struct mt9t112_priv {
 	struct v4l2_subdev		 subdev;
 	struct mt9t112_camera_info	*info;
@@ -96,6 +127,7 @@ struct mt9t112_priv {
 /* for flags */
 #define INIT_DONE	(1 << 0)
 #define PCLK_RISING	(1 << 1)
+	struct mt9t112_resolution_param	 resolution;
 };
 
 /************************************************************************
@@ -412,6 +444,453 @@ static int mt9t112_set_pll_dividers(const struct i2c_client *client,
 	return ret;
 }
 
+static int mt9t112_set_resolution_params(const struct i2c_client *client)
+{
+	int ret = 1;
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	struct mt9t112_resolution_param *resolution = &priv->resolution;
+
+	if ((priv->frame.width == 1280) && (priv->frame.height == 720)) {
+		resolution->col_strt    = 0x0004;
+		resolution->row_end     = 0x05AD;
+		resolution->col_end     = 0x050B;
+		resolution->read_mode   = 0x002C;
+		resolution->fine_cor    = 0x008C;
+		resolution->fine_min    = 0x01F1;
+		resolution->fine_max    = 0x00FF;
+		resolution->base_lines  = 0x032D;
+		resolution->min_lin_len = 0x0378;
+		resolution->line_len    = 0x091C;
+		resolution->con_width   = 0x0508;
+		resolution->con_height  = 0x02D8;
+		resolution->s_f1_50     = 0x23;
+		resolution->s_f2_50     = 0x25;
+		resolution->s_f1_60     = 0x2B;
+		resolution->s_f2_60     = 0x2D;
+		resolution->per_50      = 0xDC;
+		resolution->per_50_M    = 0x00;
+		resolution->per_60      = 0xB7;
+		resolution->fd_w_height = 0x05;
+		resolution->tx_water    = 0x0210;
+		resolution->max_fd_50   = 0x0004;
+		resolution->max_fd_60   = 0x0004;
+		resolution->targ_fd     = 0x0004;
+	} else if ((priv->frame.width <= 1024) && (priv->frame.height <= 768) &&
+		   (priv->frame.width != priv->frame.height)) {
+		resolution->col_strt    = 0x000;
+		resolution->row_end     = 0x60D;
+		resolution->col_end     = 0x80D;
+		resolution->read_mode   = 0x046C;
+		resolution->fine_cor    = 0x00CC;
+		resolution->fine_min    = 0x0381;
+		resolution->fine_max    = 0x024F;
+		resolution->base_lines  = 0x0364;
+		resolution->min_lin_len = 0x05D0;
+		resolution->line_len    = 0x07AC;
+		resolution->con_width   = 0x0408;
+		resolution->con_height  = 0x0308;
+		resolution->s_f1_50     = 0x23;
+		resolution->s_f2_50     = 0x25;
+		resolution->s_f1_60     = 0x2A;
+		resolution->s_f2_60     = 0x2C;
+		resolution->per_50      = 0x05;
+		resolution->per_50_M    = 0x01;
+		resolution->per_60      = 0xD9;
+		resolution->fd_w_height = 0x06;
+		resolution->max_fd_50   = 0x0003;
+		resolution->max_fd_60   = 0x0004;
+		resolution->targ_fd     = 0x0003;
+		if ((priv->frame.width == 1024) && (priv->frame.height == 768)) {
+			resolution->tx_water = 0x0218;
+		} else if ((priv->frame.width == 800) && (priv->frame.height == 480)) {
+			resolution->tx_water = 0x02DA;
+		} else { // 640 x 480 but use it with everything else until we figure out how to calc it
+			resolution->tx_water = 0x0352;
+		}
+	} else {
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int mt9t112_pll_setup_custom_pll(const struct i2c_client *client)
+{
+/*
+; Bypass PLL: Unchecked
+; Input Frequency: 32.000
+; Target Pads Frequency: 96.000
+; Target I2C Clock Frequency: 100.000
+; Target VCO Frequency: Unspecified
+; For Parallel Output: Checked
+; "M" Value: Unspecified
+; "N" Value: Unspecified
+;
+; Target Pads Clock Frequency: 96 MHz
+; Input Clock Frequency: 32 MHz
+;
+; Actual Pads Clock Frequency: 96 MHz
+; Sensor Core Clock Frequency: 54.857 MHz
+; SOC Clock Frequency: 54.857 MHz
+; MCU Clock Frequency: 96 MHz
+; I2C Master Clock Frequency: 99.740 KHz
+;
+; M = 24
+; N = 1
+; Fpdf = 16 MHz
+; Fvco = 768 MHz
+; P2 = 8
+; P4 = 14
+; P5 = 14
+; P6 = 8
+*/
+	int data, i, ret;
+
+	mt9t112_reg_mask_set(ret, client, 0x14, 1, 1);	// Bypass PLL
+	mt9t112_reg_mask_set(ret, client, 0X14, 2, 0);	// Power-down PLL
+	mt9t112_reg_write(ret, client, 0x0014, 0x2145);	// PLL control: BYPASS PLL = 8517
+	mt9t112_reg_write(ret, client, 0x0010, 0x0118);	// PLL Dividers = 280
+	mt9t112_reg_write(ret, client, 0x0012, 0x0070);	// PLL P Dividers = 112
+	mt9t112_reg_write(ret, client, 0x002A, 0x77EE);	// PLL P Dividers 4-5-6 = 30685
+	mt9t112_reg_write(ret, client, 0x001A, 0x218);	// Reset Misc. Control = 536
+	mt9t112_reg_write(ret, client, 0x0014, 0x2545);	// PLL control: TEST_BYPASS on = 9541
+	mt9t112_reg_write(ret, client, 0x0014, 0x2547);	// PLL control: PLL_ENABLE on = 9543
+	mt9t112_reg_write(ret, client, 0x0014, 0x2447);	// PLL control: SEL_LOCK_DET on = 9287
+	mt9t112_reg_write(ret, client, 0x0014, 0x2047);	// PLL control: TEST_BYPASS off = 8263
+
+	// Wait for the PLL to lock
+	for (i=0; i<1000; i++) {
+		mt9t112_reg_read(data, client, 0x0014);
+		if (0x8000 & data)
+			break;
+
+		mdelay(10);
+	}
+
+	mt9t112_reg_write(ret, client, 0x0014, 0x2046);	// PLL control: PLL_BYPASS off = 8262
+	mt9t112_reg_write(ret, client, 0x0022, 0x0280);	// Reference clock count for 20 us = 640
+	mt9t112_reg_write(ret, client, 0x001E, 0x0777);	// Pad Slew Rate = 1911
+	mt9t112_reg_write(ret, client, 0x0016, 0x0400);	// JPEG Clock = 1024
+
+	return ret;
+}
+
+static int mt9t112_sysctl_startup_K26A_rev_3(const struct i2c_client *client)
+{
+	int ret;
+
+	// reset
+	mt9t112_reset(client);
+
+	// Setup PLL
+	mt9t112_pll_setup_custom_pll(client);
+
+	// crank up the output slew rate (don't forget to enable these bits in TX_SS)
+	mt9t112_reg_write(ret, client, 0x001E, 0x0777);
+
+	return ret;
+}
+
+static int mt9t112_high_speed_overrides(const struct i2c_client *client)
+{
+	int ret;
+
+// Use this section to apply settings that are specific to this revision of SOC
+// or for any other specialized settings
+
+// clear the "Output Buffer Enable Adaptive Clock" bit to enable the SYSCTL
+// slew rate settings, change this in the variables and register
+
+	// PRI_A_CONFIG_JPEG_OB_TX_CONTROL_VAR
+	mt9t112_mcu_write(ret, client, VAR(26, 160), 0x082E);
+	// PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR
+	mt9t112_mcu_write(ret, client, VAR(27, 160), 0x082E);
+	//SEC_A_CONFIG_JPEG_OB_TX_CONTROL_VAR
+	mt9t112_mcu_write(ret, client, VAR(28, 160), 0x082E);
+	//SEC_B_CONFIG_JPEG_OB_TX_CONTROL_VAR
+	mt9t112_mcu_write(ret, client, VAR(29, 160), 0x082E);
+	mt9t112_reg_mask_set(ret, client, 0x3C52, 0x0040, 0);         // set this value in HW
+
+	// Set correct values for Context B FIFO control
+	// CAM1_CTX_B_RX_FIFO_TRIGGER_MARK
+	mt9t112_mcu_write(ret, client, VAR(18, 142), 32);
+	// PRI_B_CONFIG_IO_OB_MANUAL_FLAG
+	mt9t112_mcu_write(ret, client, VAR(27, 172), 0);
+
+	return ret;
+}
+
+static int mt9t112_go(const struct i2c_client *client)
+{
+	int data, i, ret;
+
+	// release MCU from standby
+	mt9t112_reg_mask_set(ret, client, 0x0018, 0x0001, 0);
+
+	// wait for K26A to come out of standby
+	for (i=0; i<100; i++) {
+		mt9t112_reg_read(data, client, 0x0018);
+		if (!(0x4000 & data))
+			break;
+
+		mdelay(10);
+	}
+
+	return ret;
+}
+
+static int mt9t112_continue(const struct i2c_client *client)
+{
+	int data, i, ret;
+
+	// clear powerup stop bit
+	mt9t112_reg_mask_set(ret, client, 0x0018, 0x0004, 0);
+
+	// wait for sequencer to enter preview state
+	for (i=0; i<100; i++) {
+		mt9t112_mcu_read(data, client, VAR8(1, 1));
+		if (data == 3)
+			break;
+
+		mdelay(10);
+	}
+
+	return ret;
+}
+
+static int mt9t112_mcu_powerup_stop_enable(const struct i2c_client *client)
+{
+	int ret;
+
+	// set powerup stop bit
+	mt9t112_reg_mask_set(ret, client, 0x0018, 0x0004, 1);
+
+	return ret;
+}
+
+static int mt9t112_custom_setup(const struct i2c_client *client)
+{
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	struct mt9t112_resolution_param *resolution = &priv->resolution;
+	int ret;
+
+	//I2C Master Clock Divider
+	mt9t112_mcu_write(ret, client, 0x6006, 0x0100);	//      = 275
+	//Output Width (A)
+	mt9t112_mcu_write(ret, client, 0x6800, priv->frame.width);
+	//Output Height (A)
+	mt9t112_mcu_write(ret, client, 0x6802, priv->frame.height);
+	//JPEG (A)
+	mt9t112_mcu_write(ret, client, 0xE88E, 0x00);	//      = 0
+	//Adaptive Output Clock (A)
+	mt9t112_mcu_mask_set(ret, client, 0x68A0, 0x0040, 0x0000);	//      = 0
+	//Row Start (A)
+	mt9t112_mcu_write(ret, client, 0x4802, 0x000);	//      = 0
+	//Column Start (A)
+	mt9t112_mcu_write(ret, client, 0x4804, resolution->col_strt);
+	//Row End (A)
+	mt9t112_mcu_write(ret, client, 0x4806, resolution->row_end);
+	//Column End (A)
+	mt9t112_mcu_write(ret, client, 0x4808, resolution->col_end);
+	//Row Speed (A)
+	mt9t112_mcu_write(ret, client, 0x480A, 0x0111);	//      = 273
+	//Read Mode (A)
+	mt9t112_mcu_write(ret, client, 0x480C, resolution->read_mode);
+	//Fine Correction (A)
+	mt9t112_mcu_write(ret, client, 0x480F, resolution->fine_cor);
+	//Fine IT Min (A)
+	mt9t112_mcu_write(ret, client, 0x4811, resolution->fine_min);
+	//Fine IT Max Margin (A)
+	mt9t112_mcu_write(ret, client, 0x4813, resolution->fine_max);
+	//Base Frame Lines (A)
+	mt9t112_mcu_write(ret, client, 0x481D, resolution->base_lines);
+	//Min Line Length (A)
+	mt9t112_mcu_write(ret, client, 0x481F, resolution->min_lin_len);
+	//Line Length (A)
+	mt9t112_mcu_write(ret, client, 0x4825, resolution->line_len);
+	//Contex Width (A)
+	mt9t112_mcu_write(ret, client, 0x482B, resolution->con_width);
+	//Context Height (A)
+	mt9t112_mcu_write(ret, client, 0x482D, resolution->con_height);
+	//Output Width (B)
+	mt9t112_mcu_write(ret, client, 0x6C00, 0x0800);	//      = 2048
+	//Output Height (B)
+	mt9t112_mcu_write(ret, client, 0x6C02, 0x0600);	//      = 1536
+	//JPEG (B)
+	mt9t112_mcu_write(ret, client, 0xEC8E, 0x01);	//      = 1
+	//Adaptive Output Clock (B)
+	mt9t112_mcu_mask_set(ret, client, 0x6CA0, 0x0040, 0x0000);	//      = 0
+	//Row Start (B)
+	mt9t112_mcu_write(ret, client, 0x484A, 0x004);	//      = 4
+	//Column Start (B)
+	mt9t112_mcu_write(ret, client, 0x484C, 0x004);	//      = 4
+	//Row End (B)
+	mt9t112_mcu_write(ret, client, 0x484E, 0x60B);	//      = 1547
+	//Column End (B)
+	mt9t112_mcu_write(ret, client, 0x4850, 0x80B);	//      = 2059
+	//Row Speed (B)
+	mt9t112_mcu_write(ret, client, 0x4852, 0x0111);	//      = 273
+	//Read Mode (B)
+	mt9t112_mcu_write(ret, client, 0x4854, 0x0024);	//      = 36
+	//Fine Correction (B)
+	mt9t112_mcu_write(ret, client, 0x4857, 0x008C);	//      = 140
+	//Fine IT Min (B)
+	mt9t112_mcu_write(ret, client, 0x4859, 0x01F1);	//      = 497
+	//Fine IT Max Margin (B)
+	mt9t112_mcu_write(ret, client, 0x485B, 0x00FF);	//      = 255
+	//Base Frame Lines (B)
+	mt9t112_mcu_write(ret, client, 0x4865, 0x06AE);	//      = 1710
+	//Min Line Length (B)
+	mt9t112_mcu_write(ret, client, 0x4867, 0x0378);	//      = 888
+	//Line Length (B)
+	mt9t112_mcu_write(ret, client, 0x486D, 0x0A3A);	//      = 2618
+	//Contex Width (B)
+	mt9t112_mcu_write(ret, client, 0x4873, 0x0808);	//      = 2056
+	//Context Height (B)
+	mt9t112_mcu_write(ret, client, 0x4875, 0x0608);	//      = 1544
+	//search_f1_50
+	mt9t112_mcu_write(ret, client, 0xC8A5, resolution->s_f1_50);
+	//search_f2_50
+	mt9t112_mcu_write(ret, client, 0xC8A6, resolution->s_f2_50);
+	//search_f1_60
+	mt9t112_mcu_write(ret, client, 0xC8A7, resolution->s_f1_60);
+	//search_f2_60
+	mt9t112_mcu_write(ret, client, 0xC8A8, resolution->s_f2_60);
+	//period_50Hz (A)
+	mt9t112_mcu_write(ret, client, 0xC844, resolution->per_50);
+	//period_50Hz (A MSB)
+	mt9t112_mcu_write(ret, client, 0xC92F, resolution->per_50_M);
+	//period_60Hz (A)
+	mt9t112_mcu_write(ret, client, 0xC845, resolution->per_60);
+	//period_60Hz (A MSB)
+	mt9t112_mcu_write(ret, client, 0xC92D, 0x00);	//      = 0
+	//period_50Hz (B)
+	mt9t112_mcu_write(ret, client, 0xC88C, 0xD2);	//      = 210
+	//period_50Hz (B) MSB
+	mt9t112_mcu_write(ret, client, 0xC930, 0x00);	//      = 0
+	//period_60Hz (B)
+	mt9t112_mcu_write(ret, client, 0xC88D, 0xAF);	//      = 175
+	//period_60Hz (B) MSB
+	mt9t112_mcu_write(ret, client, 0xC92E, 0x00);	//      = 0
+	//FD Window Height
+	mt9t112_mcu_write(ret, client, 0xB825, resolution->fd_w_height);
+	//Stat_min
+	mt9t112_mcu_write(ret, client, 0xA009, 0x02);	//      = 2
+	//Stat_max
+	mt9t112_mcu_write(ret, client, 0xA00A, 0x03);	//      = 3
+	//Min_amplitude
+	mt9t112_mcu_write(ret, client, 0xA00C, 0x0A);	//      = 10
+	//RX FIFO Watermark (A)
+	mt9t112_mcu_write(ret, client, 0x4846, 0x0080);	//      = 128
+	//TX FIFO Watermark (A)
+	mt9t112_mcu_write(ret, client, 0x68AA, resolution->tx_water);
+	//Max FD Zone 50 Hz
+	mt9t112_mcu_write(ret, client, 0x6815, resolution->max_fd_50);
+	//Max FD Zone 60 Hz
+	mt9t112_mcu_write(ret, client, 0x6817, resolution->max_fd_60);
+	//AE Target FD Zone
+	mt9t112_mcu_write(ret, client, 0x682D, resolution->targ_fd);
+	//RX FIFO Watermark (B)
+	mt9t112_mcu_write(ret, client, 0x488E, 0x0080);	//      = 128
+	//TX FIFO Watermark (B)
+	mt9t112_mcu_write(ret, client, 0x6CAA, 0x01D0);	//      = 464
+	//Refresh Sequencer Mode
+	mt9t112_mcu_write(ret, client, 0x8400, 0x06);	//      = 6
+	//Refresh Sequencer
+	mt9t112_mcu_write(ret, client, 0x8400, 0x05);	//      = 5
+
+#ifdef TEST_PATTERN
+	mt9t112_mcu_write(ret, client, VAR(24, 0x03), 0x100);
+	mt9t112_mcu_write(ret, client, VAR(24, 0x25), 0x0B);            // B - Color Bar Test Pattern (supposed to be 6 ?)
+#endif
+
+	return ret;
+}
+
+static int mt9t112_optimal_power_consumption(const struct i2c_client *client)
+{
+	int ret;
+
+	// Analog setting B
+
+	mt9t112_reg_write(ret, client, 0x3084, 0x2409);
+	mt9t112_reg_write(ret, client, 0x3092, 0x0A49);
+	mt9t112_reg_write(ret, client, 0x3094, 0x4949);
+	mt9t112_reg_write(ret, client, 0x3096, 0x4950);
+
+	return ret;
+}
+
+static int mt9t112_blooming_row_pattern(const struct i2c_client *client)
+{
+	int ret;
+
+	// Improve high light image quality
+	// [CAM1_CTX_A_COARSE_ITMIN]
+	mt9t112_mcu_write(ret, client, 0x4815, 0x0004);
+	// [CAM1_CTX_B_COARSE_ITMIN]
+	mt9t112_mcu_write(ret, client, 0x485D, 0x0004);
+
+	return ret;
+}
+
+static int mt9t112_set_orientation(const struct i2c_client *client, int flip)
+{
+	int ret;
+
+	// if flip = 0 set [normal]
+	// if flip = 1 set [horizontal mirror]
+	// if flip = 2 set [vertical flip]
+	// if flip = 3 set [rotate 180]
+	flip &= 0x3;
+
+	// [CAM1_CTX_A_READ_MODE]
+	mt9t112_mcu_mask_set(ret, client, VAR(18, 0x000C), 0x0003, flip);
+	// [CAM1_CTX_A_PIXEL_ORDER]
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x000E), flip);
+
+	// [CAM1_CTX_B_READ_MODE]
+	mt9t112_mcu_mask_set(ret, client, VAR(18, 0x0054), 0x0003, flip);
+	// [CAM1_CTX_B_PIXEL_ORDER]
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x0056), flip);
+
+	// [SEQ_CMD]
+	mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06);
+
+	return ret;
+}
+
+static int mt9t112_init_camera_optimized(const struct i2c_client *client)
+{
+	int ret;
+
+	// basic startup
+	ECHECKER(ret, mt9t112_sysctl_startup_K26A_rev_3(client));
+
+	// enable powerup stop
+	ECHECKER(ret, mt9t112_mcu_powerup_stop_enable(client));
+
+	// start MCU
+	ECHECKER(ret, mt9t112_go(client));
+
+	// customize the configuration
+	ECHECKER(ret, mt9t112_custom_setup(client));
+
+	// enable operation with fastest clocks
+	ECHECKER(ret, mt9t112_high_speed_overrides(client));
+
+	// Optimal power consumption setting
+	ECHECKER(ret, mt9t112_optimal_power_consumption(client));
+
+	// load anti-blooming settings
+	ECHECKER(ret, mt9t112_blooming_row_pattern(client));
+
+	// continue after powerup stop
+	ECHECKER(ret, mt9t112_continue(client));
+
+	return ret;
+}
+
 static int mt9t112_init_pll(const struct i2c_client *client)
 {
 	struct mt9t112_priv *priv = to_mt9t112(client);
@@ -802,6 +1281,7 @@ static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable)
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct mt9t112_priv *priv = to_mt9t112(client);
 	int ret = 0;
+	int optimize = 0;
 
 	if (!enable) {
 		/* FIXME
@@ -830,15 +1310,33 @@ static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable)
 		priv->flags |= INIT_DONE;
 	}
 
+	// fill the structure with new resolution parameters
+	optimize = mt9t112_set_resolution_params(client);
+
+	if (optimize)
+		ECHECKER(ret, mt9t112_init_camera_optimized(client));
+	else
+		ECHECKER(ret, mt9t112_init_camera(client));
+
+	/* Invert PCLK (Data sampled on falling edge of pixclk) */
+	mt9t112_reg_write(ret, client, 0x3C20, (PCLK_RISING & priv->flags ? 0x0001 : 0x0000));
+	mdelay(5);
+
 	mt9t112_mcu_write(ret, client, VAR(26, 7), priv->format->fmt);
 	mt9t112_mcu_write(ret, client, VAR(26, 9), priv->format->order);
 	mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06);
 
-	mt9t112_set_a_frame_size(client,
+	if (!optimize) {
+		mt9t112_set_a_frame_size(client,
 				 priv->frame.width,
 				 priv->frame.height);
 
-	ECHECKER(ret, mt9t112_auto_focus_trigger(client));
+		ECHECKER(ret, mt9t112_auto_focus_trigger(client));
+	}
+
+	if (priv->info->flags & MT9T112_FLAG_VFLIP) {
+		ECHECKER(ret, mt9t112_set_orientation(client, 2));
+	}
 
 	dev_dbg(&client->dev, "format : %d\n", priv->format->code);
 	dev_dbg(&client->dev, "size   : %d x %d\n",
diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig
index cb6791e..06baabf 100644
--- a/drivers/media/platform/soc_camera/Kconfig
+++ b/drivers/media/platform/soc_camera/Kconfig
@@ -86,3 +86,10 @@ config VIDEO_ATMEL_ISI
 	  This module makes the ATMEL Image Sensor Interface available
 	  as a v4l2 device.
 
+config VIDEO_QL_CAMIF
+	tristate "QuickLogic Camera Interface support (EXPERIMENTAL)"
+	depends on VIDEO_DEV && SOC_CAMERA && SOC_AM33XX && EXPERIMENTAL
+	select VIDEOBUF2_DMA_CONTIG
+	---help---
+	  This is a v4l2 driver for the QuickLogic CAMIF controller.
+
diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile
index 136b7f8..d7ba0eb 100644
--- a/drivers/media/platform/soc_camera/Makefile
+++ b/drivers/media/platform/soc_camera/Makefile
@@ -10,5 +10,6 @@ obj-$(CONFIG_VIDEO_OMAP1)		+= omap1_camera.o
 obj-$(CONFIG_VIDEO_PXA27x)		+= pxa_camera.o
 obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)	+= sh_mobile_ceu_camera.o
 obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2)	+= sh_mobile_csi2.o
+obj-$(CONFIG_VIDEO_QL_CAMIF)		+= cssp_camera.o
 
 ccflags-y += -I$(srctree)/drivers/media/i2c/soc_camera
diff --git a/drivers/media/platform/soc_camera/cssp_camera.c b/drivers/media/platform/soc_camera/cssp_camera.c
new file mode 100644
index 0000000..119c432
--- /dev/null
+++ b/drivers/media/platform/soc_camera/cssp_camera.c
@@ -0,0 +1,1831 @@
+/*
+ * cssp-camera driver
+ *
+ * Based on Vivi driver
+ *
+ * Copyright (C) 2012 QuickLogic Corp.
+ *
+ * Developed for QuickLogic by:
+ * Damian Eppel <damian.eppel@teleca.com>
+ * Przemek Szewczyk <przemek.szewczyk@teleca.com>
+ * Dan Aizenstros <daizenstros@quicklogic.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 DEBUG
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_data/edma.h>
+#include <linux/clk.h>
+// V4L2 Interface *********************
+#include <media/soc_camera.h>
+#include <media/v4l2-mediabus.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/mt9t112.h>
+//*************************************
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_dma.h>
+#include <linux/of_gpio.h>
+#include <linux/of_i2c.h>
+
+#include <linux/rstctl.h>
+
+static unsigned video_nr = -1;
+module_param(video_nr, uint, 0644);
+MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
+
+static unsigned int vid_limit = 6;
+module_param(vid_limit, uint, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
+#define INIT_WIDTH 640
+#define INIT_HEIGHT 480
+
+#define MAX_WIDTH 2048
+#define MAX_HEIGHT 1536
+
+#define BYTES_PER_PIXEL 2
+
+/* PaRAM.opt: */
+#define TCC(v) (((v) & 0x3f) << 12)
+/* PaRAM.a_b_cnt: */
+#define ACNT(v) ((v) & 0xffff)
+#define BCNT(v) (((v) & 0xffff) << 16)
+/* PaRAM.src_dst_bidx: */
+#define SRCBIDX(v) ((v) & 0xffff)
+#define DSTBIDX(v) (((v) & 0xffff) << 16)
+/* PaRAM.link_bcntrld: */
+#define LINK(v) ((v) & 0xffff)
+#define BCNTRLD(v) (((v) & 0xffff) << 16)
+/* PaRAM.src_dst_cidx: */
+#define SRCCIDX(v) ((v) & 0xffff)
+#define DSTCIDX(v) (((v) & 0xffff) << 16)
+/* PaRAM.ccnt: */
+#define CCNT(v) ((v) & 0xffff)
+
+
+struct cssp_cam_platform_data {
+	struct i2c_board_info *cam_i2c_board_info;
+	const char *cam_clk_name;
+	u32 cam_clk_rate;
+	int dma_ch;
+	int gpio_reset_pin;
+};
+
+struct cssp_cam_platform_data_storage {
+	struct cssp_cam_platform_data pdata;
+	struct i2c_board_info i2c_camera;
+	struct soc_camera_link camera_link;
+	/* only support mt9t112 for now */
+	struct mt9t112_camera_info mt9t111_cam_info;
+};
+
+#define to_cssp_platform_data_storage(_x) container_of(_x, \
+		struct cssp_cam_platform_data_storage, pdata)
+
+
+/* ------------------------------------------------------------------
+	video Basic structures
+   ------------------------------------------------------------------*/
+
+struct cssp_cam_fmt {
+	char	*name;
+	u32	fourcc;          /* v4l2 format id */
+	int	depth;
+	enum v4l2_mbus_pixelcode code;
+};
+
+/* buffer for one video frame */
+struct cssp_cam_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct vb2_buffer	vb;
+	struct list_head	list;
+	struct cssp_cam_fmt	*fmt;
+	unsigned long		queued_jiffies;
+};
+
+#define to_cssp_cam_buffer(_x) container_of(_x, struct cssp_cam_buffer, vb)
+
+struct cssp_cam_dmaqueue {
+	struct list_head	active;
+	int			count;
+};
+
+struct cssp_cam_dev {
+	struct v4l2_device		v4l2_dev;
+	struct v4l2_ctrl_handler	ctrl_handler;
+	struct v4l2_subdev		*subdev;
+
+	spinlock_t			slock;
+	struct mutex			mutex;
+
+	/* various device info */
+	struct video_device		*vdev;
+	struct platform_device		*pdev;
+
+	struct cssp_cam_dmaqueue	vidq;
+	void				*dma_cont_ctx;
+	int				streaming_started;
+	struct vb2_buffer		*current_vb[2];
+	void				*spillover;
+	dma_addr_t			spillover_dma_addr;
+
+	/* video capture */
+	struct cssp_cam_fmt		*fmt;
+	u32				width;
+	u32				height;
+	u32				bytesperline;
+	u32				sizeimage;
+	enum v4l2_colorspace		colorspace;
+	struct vb2_queue		vb_vidq;
+	enum v4l2_field			field;
+
+	/* Camera Sensor */
+	struct i2c_board_info		*camera_board_info;
+	struct clk			*camera_clk;
+
+	void __iomem			*reg_base_virt;
+	unsigned int			reg_base_phys;
+	resource_size_t			reg_size;
+	u16				mode;
+
+	int				dma_ch;
+	int				dma_link[2];
+	struct edmacc_param		dma_tr_params;
+	struct edmacc_param		dma_link_params;
+
+	u64				dma_mask;
+	int				dma_req_len;
+	int				dma_req_shift;
+
+	int				frame_cnt;
+
+	int				reset_pin;
+
+	int				rev;
+
+	/* OF build platform data here */
+	struct cssp_cam_platform_data_storage *pstore;
+
+	struct rstctl *rctrl;
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ *  QuickLoigc Camera Interface registers
+ * ---------------------------------------------------------------------------
+ */
+
+#define REG_MODE		0x00000
+#define REG_DATA		0x10000
+
+/* MODE bit shifts */
+#define FMT_2X8_EN		BIT(15) /* Enable 2 byte format on CAMIF bus (0 - 10 bit, 1 - 16 bit 2x8) */
+#define PCLK_POL		BIT(14) /* PCLK polarity (0 - rising edge, 1 - falling edge */
+#define HS_EN			BIT(13) /* High speed bus (0 =< 50 MHz, 1 > 50 MHz) */
+#define ENABLE			BIT(12)
+#define LDR_EN			BIT(11) /* Large DMA Request Support (0 - 32 bytes, 1 - 128 bytes) */
+#define REV			0xFF	/* Chip Revision mask */
+
+
+static struct cssp_cam_fmt formats[] = {
+	{
+		.name	= "4:2:2, packed, YUYV",
+		.fourcc	= V4L2_PIX_FMT_YUYV,
+		.depth	= 16,
+		.code	= V4L2_MBUS_FMT_YUYV8_2X8,
+	},
+/*
+ * UYVY doesn't work properly. VYUY and YVYU are not tested.
+ * So disable the UYVY, VYUY and YVYU modes for now
+ */
+#if 0
+	{
+		.name	= "4:2:2, packed, UYVY",
+		.fourcc	= V4L2_PIX_FMT_UYVY,
+		.depth	= 16,
+		.code	= V4L2_MBUS_FMT_UYVY8_2X8,
+	},
+	{
+		.name	= "4:2:2, packed, VYUY",
+		.fourcc	= V4L2_PIX_FMT_VYUY,
+		.depth	= 16,
+		.code	= V4L2_MBUS_FMT_VYUY8_2X8,
+	},
+	{
+		.name	= "4:2:2, packed, YVYU",
+		.fourcc	= V4L2_PIX_FMT_YVYU,
+		.depth	= 16,
+		.code	= V4L2_MBUS_FMT_YVYU8_2X8,
+	},
+#endif
+	{
+		.name	= "RGB565 (LE)",
+		.fourcc	= V4L2_PIX_FMT_RGB565,
+		.depth	= 16,
+		.code	= V4L2_MBUS_FMT_RGB565_2X8_LE,
+	},
+	{
+		.name	= "RGB555 (LE)",
+		.fourcc	= V4L2_PIX_FMT_RGB555,
+		.depth	= 16,
+		.code	= V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+	},
+};
+
+
+/***************************************************************************/
+
+static inline dma_addr_t vb2_dma_contig_cookie(void *a, void *b)
+{
+	/* Same functionality as the vb2_dma_contig_plane_paddr */
+	dma_addr_t *paddr = vb2_dma_contig_memops.cookie(b);
+
+	return *paddr;
+}
+
+/* MFC definitions */
+
+static void set_capture_enable_no_lock(struct cssp_cam_dev *dev, int enable)
+{
+	u16 val;
+
+	// readw(dev->reg_base_virt + REG_MODE);
+	if (enable) {
+		ioread16(dev->reg_base_virt + REG_MODE);
+		iowrite16(dev->mode & ~ENABLE, dev->reg_base_virt + REG_MODE);
+		ioread16(dev->reg_base_virt + REG_MODE);
+		iowrite16(dev->mode |  ENABLE, dev->reg_base_virt + REG_MODE);
+	} else {
+		ioread16(dev->reg_base_virt + REG_MODE);
+		iowrite16(dev->mode |  ENABLE, dev->reg_base_virt + REG_MODE);
+		ioread16(dev->reg_base_virt + REG_MODE);
+		iowrite16(dev->mode & ~ENABLE, dev->reg_base_virt + REG_MODE);
+	}
+
+	val = ioread16(dev->reg_base_virt + REG_MODE);
+	dev_dbg(&dev->pdev->dev, "%s enable=%d val=0x%04x\n", __func__,
+			enable, val);
+}
+
+static int set_capture_enable(struct cssp_cam_dev *dev, int enable)
+{
+	unsigned long flags;
+	unsigned long tmo;
+
+	spin_lock_irqsave(&dev->slock, flags);
+	set_capture_enable_no_lock(dev, enable);
+	spin_unlock_irqrestore(&dev->slock, flags);
+
+	/* sigh, check whether the device gets data */
+	if (enable) {
+		tmo = jiffies + msecs_to_jiffies(1000);
+		while ((ioread16(dev->reg_base_virt + REG_MODE) & 0x0100) != 0) {
+			if (time_after(jiffies, tmo))
+				break;
+			cpu_relax();
+		}
+
+		if (time_after(jiffies, tmo)) {
+			spin_lock_irqsave(&dev->slock, flags);
+			set_capture_enable_no_lock(dev, 0);
+			spin_unlock_irqrestore(&dev->slock, flags);
+			return -EAGAIN;
+		}
+	}
+	return 0;
+}
+
+static int configure_gpio(int nr, int val, const char *name)
+{
+	unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+	int ret;
+	if (!gpio_is_valid(nr))
+		return 0;
+	ret = gpio_request_one(nr, flags, name);
+	if (!ret)
+		gpio_export(nr, 0);
+	return ret;
+}
+
+static int reset_cssp(struct cssp_cam_dev *cam)
+{
+	struct platform_device *pdev = cam->pdev;
+	struct cssp_cam_platform_data *pdata = pdev->dev.platform_data;
+	int err;
+
+	cam->reset_pin = pdata->gpio_reset_pin;
+	if (!gpio_is_valid(cam->reset_pin))
+		return 0;
+
+	err = configure_gpio(cam->reset_pin, 0, "cssp_reset");
+	if (err) {
+		dev_err(&pdev->dev, "failed to configure cssp reset pin\n");
+		return -1;
+	}
+
+	mdelay(1);
+
+	gpio_direction_output(cam->reset_pin, 1);
+
+	return err;
+}
+
+#if 0
+static void dump_slot(struct cssp_cam_dev *cam, int slot, char *name)
+{
+	struct device *dev = &cam->pdev->dev;
+	struct edmacc_param p;
+
+	if (slot < 0)
+		return;
+
+	edma_read_slot(slot, &p);
+	dev_dbg(dev, "%s: 0x%x, opt=%x, src=%x, a_b_cnt=%x dst=%x\n",
+			name, slot, p.opt, p.src, p.a_b_cnt, p.dst);
+	dev_dbg(dev, "    src_dst_bidx=%x link_bcntrld=%x src_dst_cidx=%x ccnt=%x\n",
+			p.src_dst_bidx, p.link_bcntrld, p.src_dst_cidx, p.ccnt);
+}
+#endif
+
+void enqueue_dma(struct cssp_cam_dev *dev, int ch, struct vb2_buffer *vb)
+{
+	dma_addr_t dma_buf;
+	int i, rem;
+	u32 bytesperline, height;
+	u16 acnt, bcnt, ccnt;
+	struct edmacc_param params;
+
+	/* Calculate DMA transfer parameters based on DMA request length */
+	bytesperline = dev->bytesperline;
+	i = 0;
+	do {
+		rem = bytesperline % dev->dma_req_len;
+		if (rem != 0) {
+			bytesperline <<= 1;
+			i++;
+		}
+	} while (rem != 0);
+	height = dev->height >> i;
+	acnt = dev->dma_req_len;
+	bcnt = bytesperline / dev->dma_req_len;
+	ccnt = height;
+
+	if (vb != NULL)
+		dma_buf = vb2_dma_contig_plane_dma_addr(vb, 0);
+	else
+		dma_buf = dev->spillover_dma_addr;
+
+	edma_set_src(ch, dev->reg_base_phys + REG_DATA, INCR, W8BIT);
+	edma_set_dest(ch, dma_buf, INCR, W8BIT);
+	edma_set_src_index(ch, 0, 0);
+	edma_set_dest_index(ch,
+			dev->dma_req_len,	/* dest bidx */
+			dev->dma_req_len);	/* dest cidx */
+	edma_set_transfer_params(ch,
+			dev->dma_req_len,			/* acnt */
+			bytesperline / dev->dma_req_len,	/* bcnt */
+			height,					/* ccnt */
+			bytesperline / dev->dma_req_len,	/* bcnt_rld */
+			ASYNC);
+
+	/*
+	 * Issue transfer completion IRQ when the channel completes
+	 * a transfer, and then always reload from the same slot
+	 */
+	edma_read_slot(ch, &params);
+	params.opt |= TCINTEN | EDMA_TCC(EDMA_CHAN_SLOT(dev->dma_ch));
+	params.link_bcntrld = (params.link_bcntrld & ~0xffff) |
+		((EDMA_CHAN_SLOT(dev->dma_link[0]) << 5) & 0xffff);
+	edma_write_slot(ch, &params);
+
+#if 0
+	{
+	struct edmacc_param p;
+
+	edma_read_slot(ch, &p);
+	dev_dbg(&dev->pdev->dev,
+		"1. opt=%08x, src=%08x, a_b_cnt=%08x dst=%08x src_dst_bidx=%08x "
+		"link_bcntrld=%08x src_dst_cidx=%08x ccnt=%08x\n",
+		p.opt, p.src, p.a_b_cnt, p.dst, p.src_dst_bidx,
+		p.link_bcntrld, p.src_dst_cidx, p.ccnt);
+
+	p.opt = TCINTEN | TCC(dev->dma_ch);
+	p.src = dev->reg_base_phys + REG_DATA;
+	p.dst = dma_buf;
+	p.a_b_cnt = ACNT(dev->dma_req_len) | BCNT((INIT_WIDTH * BYTES_PER_PIXEL) / dev->dma_req_len);
+	p.src_dst_bidx = SRCBIDX(0) | DSTBIDX(dev->dma_req_len);
+	p.link_bcntrld = BCNTRLD((INIT_WIDTH * BYTES_PER_PIXEL) / dev->dma_req_len) | LINK(0xffff);
+	p.src_dst_cidx = SRCCIDX(0) | DSTCIDX(dev->dma_req_len);
+	p.ccnt = CCNT(INIT_HEIGHT);
+
+	dev_dbg(&dev->pdev->dev,
+		"2. opt=%08x, src=%08x, a_b_cnt=%08x dst=%08x src_dst_bidx=%08x "
+		"link_bcntrld=%08x src_dst_cidx=%08x ccnt=%08x\n",
+		p.opt, p.src, p.a_b_cnt, p.dst, p.src_dst_bidx,
+		p.link_bcntrld, p.src_dst_cidx, p.ccnt);
+
+	}
+#endif
+
+	// dump_slot(dev, ch, "q");
+
+	/* 
+	param->a_b_cnt = ACNT(dev->dma_req_len) | BCNT(bytesperline / dev->dma_req_len);
+	param->src_dst_bidx = SRCBIDX(0) | DSTBIDX(dev->dma_req_len);
+	param->link_bcntrld = BCNTRLD(bytesperline / dev->dma_req_len) | LINK(0xffff);
+	param->src_dst_cidx = SRCCIDX(0) | DSTCIDX(dev->dma_req_len);
+	param->ccnt = CCNT(height);
+	*/
+
+}
+
+static int fillup_dma(struct cssp_cam_dev *dev)
+{
+	struct cssp_cam_dmaqueue *dma_q = &dev->vidq;
+	struct cssp_cam_buffer *buf;
+	struct vb2_buffer *vb;
+	int i, ch, cnt;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->slock, flags);
+
+	/* while there's a buffer queued, and there's space */
+	cnt = 0;
+	while (!list_empty(&dma_q->active) &&
+		(dev->current_vb[0] == NULL || dev->current_vb[1] == NULL)) {
+
+		if (dev->current_vb[0] == NULL) {
+			i = 0;
+			ch = dev->dma_ch;
+		} else {
+			i = 1;
+			ch = dev->dma_link[0];
+		}
+
+		buf = list_entry(dma_q->active.next,
+				struct cssp_cam_buffer, list);
+		list_del(&buf->list);
+		dma_q->count--;
+
+		vb = &buf->vb;
+		enqueue_dma(dev, ch, vb);
+		dev->current_vb[i] = vb;
+
+		cnt++;
+		/* dev_dbg(&pdev->dev, "queued vb %p (#=%d, ch=%d)\n", vb, i, ch); */
+	}
+	spin_unlock_irqrestore(&dev->slock, flags);
+
+	return cnt;
+}
+
+static void dma_callback(unsigned lch, u16 ch_status, void *data)
+{
+	struct cssp_cam_dev *dev = data;
+	struct vb2_buffer *vb;
+	unsigned long flags;
+	struct cssp_cam_buffer *buf;
+	struct cssp_cam_dmaqueue *dma_q = &dev->vidq;
+	int ch;
+
+	if (ch_status != DMA_COMPLETE) {
+		dev_dbg(&dev->pdev->dev, "%s - missed interrupt\n",
+				__func__);
+		return;
+	}
+
+	spin_lock_irqsave(&dev->slock, flags);
+
+	vb = dev->current_vb[0];
+	dev->current_vb[0] = dev->current_vb[1];
+	dev->current_vb[1] = NULL;
+
+	/* if there's a buffer, link to the next */
+	ch = dev->dma_link[0];
+
+	if (!list_empty(&dma_q->active)) {
+
+		buf = list_entry(dma_q->active.next,
+				struct cssp_cam_buffer, list);
+		list_del(&buf->list);
+		dma_q->count--;
+
+		enqueue_dma(dev, ch, &buf->vb);
+		dev->current_vb[1] = &buf->vb;
+	} else {
+		/* no buffer, we need to put the spillover there */
+		enqueue_dma(dev, ch, NULL);
+	}
+
+	spin_unlock_irqrestore(&dev->slock, flags);
+
+	/* fillup_dma(dev); */
+
+	if (vb != NULL) {
+		/* queue the current buffer */
+		buf = to_cssp_cam_buffer(vb);
+
+		vb->v4l2_buf.field = dev->field;
+		vb->v4l2_buf.sequence = dev->frame_cnt++;
+		do_gettimeofday(&vb->v4l2_buf.timestamp);
+		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+
+		/* dev_dbg(&dev->pdev->dev, "[%p/%d] done\n",
+				buf, buf->vb.v4l2_buf.index); */
+
+	}
+}
+
+static int configure_edma(struct cssp_cam_dev *cam)
+{
+	struct platform_device *pdev = cam->pdev;
+	struct cssp_cam_platform_data *pdata = pdev->dev.platform_data;
+	int dma_channel;
+	int ret;
+
+	dma_channel = pdata->dma_ch;
+
+	/* wtf? do we need to this here? */
+	pdev->dev.dma_mask = &cam->dma_mask;
+	pdev->dev.coherent_dma_mask = (u32)~0;
+	if (dma_set_mask(&pdev->dev, (u32)~0)) {
+		dev_err(&pdev->dev, "failed setting mask for DMA\n");
+		return -EINVAL;
+	}
+	ret = edma_alloc_channel(dma_channel, dma_callback, cam, EVENTQ_0);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "allocating channel for DMA failed\n");
+		return ret;
+	}
+	cam->dma_ch = ret;
+	dev_info(&pdev->dev, "dma_ch=%d\n", cam->dma_ch);
+
+	/* allocate link channels */
+	ret = edma_alloc_slot(EDMA_CTLR(cam->dma_ch), EDMA_SLOT_ANY);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "allocating slot for DMA failed\n");
+		return ret;
+	}
+	cam->dma_link[0] = ret;
+	dev_info(&pdev->dev, "dma_link[0]=%d\n", cam->dma_link[0]);
+
+	return 0;
+}
+
+static int configure_cssp(struct cssp_cam_dev *cam)
+{
+	struct platform_device *pdev = cam->pdev;
+	int ret = 0;
+	unsigned int val;
+	struct resource *res;
+
+	ret = reset_cssp(cam);
+	if (ret)
+		return ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no mem resource\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * Request the region.
+	 */
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev, "request_mem_region failed\n");
+		return -EBUSY;
+	}
+
+	cam->reg_base_phys = res->start;
+	cam->reg_size = resource_size(res);
+
+	cam->reg_base_virt = ioremap(cam->reg_base_phys, cam->reg_size);
+	if (cam->reg_base_virt == NULL) {
+		dev_err(&pdev->dev, "ioremap of registers region failed\n");
+		release_mem_region(cam->reg_base_phys, cam->reg_size);
+		return -ENOMEM;
+	}
+
+	/* double reads */
+	readw(cam->reg_base_virt + REG_MODE);
+	val = readw(cam->reg_base_virt + REG_MODE);
+	cam->rev = val & REV;
+	dev_info(&pdev->dev, "CSSP Revision %c%d\n",
+			'A' + ((cam->rev & 0xf0) >> 4), cam->rev & 0x0f);
+
+	if (cam->rev > 3) {
+		cam->dma_req_len = 128;
+		cam->dma_req_shift = 7;
+	} else {
+		cam->dma_req_len = 32;
+		cam->dma_req_shift = 5;
+	}
+
+	return 0;
+}
+
+static int configure_camera_sensor(struct cssp_cam_dev *cam)
+{
+	struct i2c_board_info *info = cam->camera_board_info;
+	struct i2c_client *client;
+	struct i2c_adapter *adapter;
+	struct v4l2_subdev *subdev;
+	int ret;
+	struct v4l2_mbus_framefmt f_format = {
+			.width = INIT_WIDTH,
+			.height = INIT_HEIGHT,
+			.code = V4L2_MBUS_FMT_YUYV8_2X8,
+			.colorspace = V4L2_COLORSPACE_JPEG,
+	};
+
+	/* Enable the clock just for the time of loading the camera driver and disable after that */
+	/* It is going to be be re-enabled later, when camera will be in use */
+	ret = clk_prepare_enable(cam->camera_clk);
+	BUG_ON(ret != 0);
+	msleep(100); // let the clock stabilize
+
+	adapter	= i2c_get_adapter(((struct soc_camera_link *)(info->platform_data))->i2c_adapter_id);
+	if (!adapter) {
+		dev_err(&cam->pdev->dev, "failed to get i2c adapter...\n");
+		return -ENODEV;
+	}
+
+	client = i2c_new_device(adapter, info);
+	i2c_put_adapter(adapter);
+
+	if (client == NULL) {
+		return -ENODEV;
+	}
+
+	subdev = (struct v4l2_subdev *)i2c_get_clientdata(client);
+	if (subdev == NULL) {
+		i2c_unregister_device(client);
+		return -ENODEV;
+	}
+
+	cam->subdev = subdev;
+
+	v4l2_subdev_call(subdev, video, s_mbus_fmt, &f_format);
+
+	clk_disable_unprepare(cam->camera_clk);
+
+	return 0;
+}
+
+static int start_camera_sensor(struct cssp_cam_dev *cam)
+{
+	int ret;
+
+	ret = v4l2_subdev_call(cam->subdev, video, s_stream, 1);
+	if (ret != 0) {
+		dev_err(&cam->pdev->dev, "%s: v4l2_subdev_call failed\n",
+				__func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void stop_camera_sensor(struct cssp_cam_dev *cam)
+{
+	v4l2_subdev_call(cam->subdev, video, s_stream, 0);
+}
+
+static struct cssp_cam_fmt *get_format(struct v4l2_format *f)
+{
+	struct cssp_cam_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < ARRAY_SIZE(formats); k++) {
+		fmt = &formats[k];
+		if (fmt->fourcc == f->fmt.pix.pixelformat)
+			break;
+	}
+
+	if (k == ARRAY_SIZE(formats))
+		return NULL;
+
+	return &formats[k];
+}
+
+
+/* ------------------------------------------------------------------
+	Videobuf operations
+   ------------------------------------------------------------------*/
+
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+				unsigned int *nbuffers, unsigned int *nplanes,
+				unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
+	unsigned long size;
+
+	size = dev->sizeimage;
+
+	if (0 == *nbuffers)
+		*nbuffers = 32;
+
+	while (size * *nbuffers > vid_limit * 1024 * 1024)
+		(*nbuffers)--;
+
+	*nplanes = 1;
+
+	sizes[0] = size;
+
+	alloc_ctxs[0] = dev->dma_cont_ctx;
+
+	dev->frame_cnt = 0;
+
+	dev_dbg(&dev->pdev->dev, "%s, count=%d, size=%ld\n", __func__,
+			*nbuffers, size);
+
+	return 0;
+}
+
+static int buffer_init(struct vb2_buffer *vb)
+{
+	struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+
+	BUG_ON(NULL == dev->fmt);
+
+	return 0;
+}
+
+static int buffer_prepare(struct vb2_buffer *vb)
+{
+	struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+	struct cssp_cam_buffer *buf =
+		container_of(vb, struct cssp_cam_buffer, vb);
+	unsigned long size;
+
+	BUG_ON(NULL == dev->fmt);
+
+	/*
+	 * Theses properties only change when queue is idle, see s_fmt.
+	 * The below checks should not be performed here, on each
+	 * buffer_prepare (i.e. on each qbuf). Most of the code in this function
+	 * should thus be moved to buffer_init and s_fmt.
+	 */
+	if (dev->width  < 48 || dev->width  > MAX_WIDTH ||
+	    dev->height < 32 || dev->height > MAX_HEIGHT)
+		return -EINVAL;
+
+	size = dev->sizeimage;
+	if (vb2_plane_size(vb, 0) < size) {
+		dev_err(&dev->pdev->dev, "%s data will not fit into "
+				"plane (%lu < %lu)\n",
+				__func__, vb2_plane_size(vb, 0), size);
+		return -EINVAL;
+	}
+
+	vb2_set_plane_payload(&buf->vb, 0, size);
+
+	buf->fmt = dev->fmt;
+
+	return 0;
+}
+
+static int buffer_finish(struct vb2_buffer *vb)
+{
+	return 0;
+}
+
+static void buffer_cleanup(struct vb2_buffer *vb)
+{
+	struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
+{
+	struct cssp_cam_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+	struct cssp_cam_buffer *buf = container_of(vb, struct cssp_cam_buffer, vb);
+	struct cssp_cam_dmaqueue *vidq = &dev->vidq;
+	unsigned long flags = 0;
+
+	/* just add it to the queue */
+	spin_lock_irqsave(&dev->slock, flags);
+	list_add_tail(&buf->list, &vidq->active);
+	vidq->count++;
+	spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
+	struct platform_device *pdev = dev->pdev;
+	int ret, retries;
+
+	dev_dbg(&dev->pdev->dev, "%s count=%d\n", __func__, count);
+
+	retries = 0;
+
+	set_capture_enable(dev, 0);
+
+	ret = clk_prepare_enable(dev->camera_clk);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "%s: clk_enable failed\n",
+				__func__);
+		return ret;
+	}
+	msleep(100); /* let the clock stabilize */
+
+	fillup_dma(dev);
+
+	// Enable DMA
+	ret = edma_start(dev->dma_ch);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "edma_start failed\n");
+		return ret;
+	}
+
+again:
+	ret = start_camera_sensor(dev);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "start_camera_sensor failed\n");
+		return ret;
+	}
+
+	// Enable data capture
+	ret = set_capture_enable(dev, 1);
+	if (ret != 0) {
+		retries++;
+		dev_warn(&pdev->dev, "no stream; retry #%d\n", retries);
+		if (retries < 3)
+			goto again;
+		goto again;
+	}
+
+	dev->streaming_started = 1;
+
+	return 0;
+}
+
+/* abort streaming and wait for last buffer */
+static int stop_streaming(struct vb2_queue *vq)
+{
+	struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
+	struct cssp_cam_dmaqueue *dma_q = &dev->vidq;
+	struct cssp_cam_buffer *buf;
+	unsigned long flags;
+	struct vb2_buffer *vb;
+	int i;
+
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+	// Disable DMA
+	edma_stop(dev->dma_ch);
+
+	// Disable data capture
+	set_capture_enable(dev, 0);
+
+	stop_camera_sensor(dev);
+
+	clk_disable_unprepare(dev->camera_clk);
+
+	dev->streaming_started = 0;
+
+	/* Release all active buffers */
+	spin_lock_irqsave(&dev->slock, flags);
+
+	for (i = 0; i < 2; i++) {
+		vb = dev->current_vb[i];
+		if (vb == NULL)
+			continue;
+		dev->current_vb[i] = NULL;
+
+		buf = to_cssp_cam_buffer(vb);
+
+		vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+
+		dev_dbg(&dev->pdev->dev, "[%p/%d] in flight\n",
+				buf, buf->vb.v4l2_buf.index);
+	}
+
+	while (!list_empty(&dma_q->active)) {
+
+		buf = list_entry(dma_q->active.next,
+				struct cssp_cam_buffer, list);
+		list_del(&buf->list);
+
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+
+		dev_dbg(&dev->pdev->dev, "[%p/%d] queued\n",
+				buf, buf->vb.v4l2_buf.index);
+	}
+	spin_unlock_irqrestore(&dev->slock, flags);
+
+	return 0;
+}
+
+static void cssp_cam_lock(struct vb2_queue *vq)
+{
+	struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
+	mutex_lock(&dev->mutex);
+}
+
+static void cssp_cam_unlock(struct vb2_queue *vq)
+{
+	struct cssp_cam_dev *dev = vb2_get_drv_priv(vq);
+	mutex_unlock(&dev->mutex);
+}
+
+static struct vb2_ops cssp_cam_video_qops = {
+	.queue_setup		= queue_setup,
+	.buf_init		= buffer_init,
+	.buf_prepare		= buffer_prepare,
+	.buf_finish		= buffer_finish,
+	.buf_cleanup		= buffer_cleanup,
+	.buf_queue		= buffer_queue,
+	.start_streaming	= start_streaming,
+	.stop_streaming		= stop_streaming,
+	.wait_prepare		= cssp_cam_unlock,
+	.wait_finish		= cssp_cam_lock,
+};
+
+/* ------------------------------------------------------------------
+	IOCTL vidioc handling
+   ------------------------------------------------------------------*/
+
+static int vidioc_querycap(struct file *file, void *priv,
+					struct v4l2_capability *cap)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+	strcpy(cap->driver, "cssp_camera");
+	strcpy(cap->card, "cssp_camera");
+	strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+			    V4L2_CAP_READWRITE;
+	return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_fmtdesc *f)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+	struct cssp_cam_fmt *fmt;
+
+	dev_dbg(&dev->pdev->dev, "%s index=%d\n", __func__, f->index);
+
+	if (f->index >= ARRAY_SIZE(formats))
+		return -EINVAL;
+
+	fmt = &formats[f->index];
+
+	strlcpy(f->description, fmt->name, sizeof(f->description));
+	f->pixelformat = fmt->fourcc;
+	return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+
+	dev_dbg(&dev->pdev->dev, "%s: dev->width=%u dev->height=%u "
+			"dev->sizeimage=%u\n", __func__,
+			dev->width, dev->height, dev->sizeimage);
+
+	f->fmt.pix.width	= dev->width;
+	f->fmt.pix.height	= dev->height;
+	f->fmt.pix.field	= dev->field;
+	f->fmt.pix.pixelformat	= dev->fmt->fourcc;
+	f->fmt.pix.bytesperline	= dev->bytesperline;
+	f->fmt.pix.sizeimage	= dev->sizeimage;
+	f->fmt.pix.colorspace	= dev->colorspace;
+
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+			struct v4l2_format *f)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+	struct cssp_cam_fmt *fmt;
+	struct v4l2_mbus_framefmt mbus_fmt;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+	fmt = get_format(f);
+	if (!fmt) {
+		dev_err(&dev->pdev->dev, "Fourcc format (0x%08x) invalid.\n",
+			f->fmt.pix.pixelformat);
+		return -EINVAL;
+	}
+
+	v4l2_fill_mbus_format(&mbus_fmt, pix, fmt->code);
+	v4l2_subdev_call(dev->subdev, video, try_mbus_fmt, &mbus_fmt);
+	v4l2_fill_pix_format(pix, &mbus_fmt);
+	pix->bytesperline = (pix->width * fmt->depth) >> 3;
+	pix->sizeimage = pix->height * pix->bytesperline;
+
+	if ((pix->sizeimage % dev->dma_req_len) != 0)
+		return -EINVAL;
+
+	switch (mbus_fmt.field) {
+	case V4L2_FIELD_ANY:
+		pix->field = V4L2_FIELD_NONE;
+		break;
+	case V4L2_FIELD_NONE:
+		break;
+	default:
+		dev_err(&dev->pdev->dev, "Field type %d unsupported.\n", mbus_fmt.field);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+	struct vb2_queue *q = &dev->vb_vidq;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_mbus_framefmt mbus_fmt;
+	int ret;
+
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+	ret = vidioc_try_fmt_vid_cap(file, priv, f);
+	if (ret < 0) {
+		dev_err(&dev->pdev->dev, "%s: vidioc_try_fmt_vid_cap failed\n",
+				__func__);
+		return ret;
+	}
+
+	if (vb2_is_streaming(q)) {
+		dev_err(&dev->pdev->dev, "%s device busy\n", __func__);
+		return -EBUSY;
+	}
+
+	dev->fmt = get_format(f);
+	dev->width = f->fmt.pix.width;
+	dev->height = f->fmt.pix.height;
+	dev->field = f->fmt.pix.field;
+	dev->colorspace = f->fmt.pix.colorspace;
+	dev->bytesperline = f->fmt.pix.bytesperline;
+	dev->sizeimage = f->fmt.pix.sizeimage;
+
+	dev_dbg(&dev->pdev->dev, "width=%u height=%u byteperline=%u\n",
+			dev->width, dev->height, dev->bytesperline);
+
+	/* Set the sensor into the new format */
+	v4l2_fill_mbus_format(&mbus_fmt, pix, dev->fmt->code);
+	v4l2_subdev_call(dev->subdev, video, s_mbus_fmt, &mbus_fmt);
+
+	return 0;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+			  struct v4l2_requestbuffers *p)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+	return vb2_reqbufs(&dev->vb_vidq, p);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+	return vb2_querybuf(&dev->vb_vidq, p);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+
+	return vb2_qbuf(&dev->vb_vidq, p);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+
+	return vb2_dqbuf(&dev->vb_vidq, p, file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+	return vb2_streamon(&dev->vb_vidq, i);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+	return vb2_streamoff(&dev->vb_vidq, i);
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+	v4l2_ctrl_handler_log_status(&dev->ctrl_handler, dev->v4l2_dev.name);
+	return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+				struct v4l2_input *inp)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+	if (inp->index > 0)
+		return -EINVAL;
+
+	inp->type = V4L2_INPUT_TYPE_CAMERA;
+	sprintf(inp->name, "Camera %u", inp->index);
+
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+	*i = 0;
+
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+
+	dev_dbg(&dev->pdev->dev, "%s\n", __func__);
+
+	if (i > 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int vidioc_subscribe_event(struct v4l2_fh *fh,
+				const struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_CTRL:
+		return v4l2_event_subscribe(fh, sub, 0, NULL);
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct v4l2_ioctl_ops cssp_cam_ioctl_ops = {
+	.vidioc_querycap		= vidioc_querycap,
+	.vidioc_enum_fmt_vid_cap	= vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap		= vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap		= vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap		= vidioc_s_fmt_vid_cap,
+	.vidioc_reqbufs			= vidioc_reqbufs,
+	.vidioc_querybuf		= vidioc_querybuf,
+	.vidioc_qbuf			= vidioc_qbuf,
+	.vidioc_dqbuf			= vidioc_dqbuf,
+	.vidioc_enum_input		= vidioc_enum_input,
+	.vidioc_g_input			= vidioc_g_input,
+	.vidioc_s_input			= vidioc_s_input,
+	.vidioc_streamon		= vidioc_streamon,
+	.vidioc_streamoff		= vidioc_streamoff,
+	.vidioc_log_status		= vidioc_log_status,
+	.vidioc_subscribe_event		= vidioc_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+};
+
+
+/* ------------------------------------------------------------------
+	File operations
+   ------------------------------------------------------------------*/
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+	struct v4l2_fh *fh = file->private_data;
+	struct vb2_queue *q = &dev->vb_vidq;
+	unsigned int res;
+
+	/* dev_dbg(&dev->pdev->dev, "%s\n", __func__); */
+
+	res = vb2_poll(q, file, wait);
+	if (v4l2_event_pending(fh))
+		res |= POLLPRI;
+	else
+		poll_wait(file, &fh->wait, wait);
+	return res;
+}
+
+static int video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct cssp_cam_dev *dev = video_drvdata(file);
+	int ret;
+
+	dev_dbg(&dev->pdev->dev, "mmap called, vma=0x%08lx\n",
+			(unsigned long)vma);
+
+	ret = vb2_mmap(&dev->vb_vidq, vma);
+	dev_dbg(&dev->pdev->dev, "vma start=0x%08lx, size=%ld, ret=%d\n",
+		(unsigned long)vma->vm_start,
+		(unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
+		ret);
+	return ret;
+}
+
+static ssize_t video_read(struct file *file, char __user *buf,
+		size_t size, loff_t *offset)
+{
+	struct cssp_cam_dev *cam_dev = video_drvdata(file);
+
+	dev_dbg(&cam_dev->pdev->dev, "%s\n", __func__);
+
+	return vb2_read(&cam_dev->vb_vidq, buf, size, offset,
+			file->f_flags & O_NONBLOCK);
+}
+
+static int video_close(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cssp_cam_dev *cam_dev = video_drvdata(file);
+
+	dev_dbg(&cam_dev->pdev->dev, "close called (dev=%s), file %p\n",
+		video_device_node_name(vdev), file);
+
+	if (v4l2_fh_is_singular_file(file))
+		vb2_queue_release(&cam_dev->vb_vidq);
+	return v4l2_fh_release(file);
+}
+
+static const struct v4l2_file_operations cssp_cam_fops = {
+	.owner		= THIS_MODULE,
+	.open		= v4l2_fh_open,
+	.release	= video_close,
+	.read		= video_read,
+	.poll		= video_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= video_mmap,
+};
+
+
+/* ------------------------------------------------------------------
+	Driver initialization
+   ------------------------------------------------------------------*/
+
+static struct video_device cssp_cam_template = {
+	.name		= "cssp_camera",
+	.fops		= &cssp_cam_fops,
+	.ioctl_ops	= &cssp_cam_ioctl_ops,
+	.minor		= -1,
+	.release	= video_device_release,
+};
+
+static int video_probe(struct cssp_cam_dev *cam_dev)
+{
+	struct video_device *vfd;
+	struct v4l2_ctrl_handler *hdl;
+	struct vb2_queue *q;
+	int ret = 0;
+
+	snprintf(cam_dev->v4l2_dev.name, sizeof(cam_dev->v4l2_dev.name),
+			"%s-%03d", "cssp_camera", 0);
+	ret = v4l2_device_register(NULL, &cam_dev->v4l2_dev);
+	if (ret)
+		goto free_dev;
+
+	cam_dev->fmt = &formats[0];
+	cam_dev->width = INIT_WIDTH;
+	cam_dev->height = INIT_HEIGHT;
+	cam_dev->bytesperline = INIT_WIDTH * BYTES_PER_PIXEL;
+	cam_dev->sizeimage = cam_dev->bytesperline * INIT_HEIGHT;
+	hdl = &cam_dev->ctrl_handler;
+	v4l2_ctrl_handler_init(hdl, 0);
+
+	if (hdl->error) {
+		ret = hdl->error;
+		goto unreg_dev;
+	}
+	cam_dev->v4l2_dev.ctrl_handler = hdl;
+
+	/* initialize locks */
+	spin_lock_init(&cam_dev->slock);
+
+	/* initialize queue */
+	q = &cam_dev->vb_vidq;
+	memset(q, 0, sizeof(cam_dev->vb_vidq));
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_READ;
+	q->drv_priv = cam_dev;
+	q->buf_struct_size = sizeof(struct cssp_cam_buffer);
+	q->ops = &cssp_cam_video_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+
+	ret = vb2_queue_init(q);
+	if (ret != 0) {
+		goto unreg_dev;
+	}
+
+	mutex_init(&cam_dev->mutex);
+
+	/* init video dma queues */
+	INIT_LIST_HEAD(&cam_dev->vidq.active);
+
+	ret = -ENOMEM;
+	vfd = video_device_alloc();
+	if (!vfd)
+		goto unreg_dev;
+
+	*vfd = cssp_cam_template;
+	vfd->v4l2_dev = &cam_dev->v4l2_dev;
+	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+
+	/*
+	 * Provide a mutex to v4l2 core. It will be used to protect
+	 * all fops and v4l2 ioctls.
+	 */
+	vfd->lock = &cam_dev->mutex;
+
+	ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
+	if (ret < 0)
+		goto rel_vdev;
+
+	video_set_drvdata(vfd, cam_dev);
+
+	if (video_nr != -1)
+		video_nr++;
+
+	cam_dev->vdev = vfd;
+	v4l2_info(&cam_dev->v4l2_dev, "V4L2 device registered as %s\n",
+	video_device_node_name(vfd));
+
+	return 0;
+
+rel_vdev:
+	video_device_release(vfd);
+unreg_dev:
+	v4l2_ctrl_handler_free(hdl);
+	v4l2_device_unregister(&cam_dev->v4l2_dev);
+free_dev:
+	return ret;
+}
+
+static int video_remove(struct cssp_cam_dev *cam_dev)
+{
+	if (cam_dev->dma_cont_ctx != NULL)
+		vb2_dma_contig_cleanup_ctx(cam_dev->dma_cont_ctx);
+
+	v4l2_info(&cam_dev->v4l2_dev, "unregistering %s\n",
+			video_device_node_name(cam_dev->vdev));
+	video_unregister_device(cam_dev->vdev);
+	v4l2_device_unregister(&cam_dev->v4l2_dev);
+	v4l2_ctrl_handler_free(&cam_dev->ctrl_handler);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+
+static const struct of_device_id cssp_camera_of_match[] = {
+	{ .compatible = "cssp-camera", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, cssp_camera_of_match);
+
+struct cssp_cam_platform_data *
+of_get_cssp_platform_data(struct platform_device *pdev)
+{
+	struct cssp_cam_platform_data *pdata;
+	struct cssp_cam_platform_data_storage *pstore;
+	struct device *dev = &pdev->dev;
+	struct device_node *np, *nps, *npc, *npa;
+	struct i2c_adapter *adap;
+	struct of_phandle_args args;
+	u32 val, valarr[9];
+	int ret, found, gpio_orientation_pin;
+
+	np = dev->of_node;
+	nps = NULL;
+	npc = NULL;
+	npa = NULL;
+	adap = NULL;
+	memset(&args, 0, sizeof(args));
+	pstore = NULL;
+	gpio_orientation_pin = -1;
+
+	if (np == NULL) {
+		dev_err(dev, "No OF device node\n");
+		goto err_fail;
+	}
+	pstore = devm_kzalloc(dev, sizeof(*pstore), GFP_KERNEL);
+	if (pstore == NULL) {
+		dev_err(dev, "Failed to allocate platform data storage\n");
+		goto err_fail;
+	}
+
+	/* link the structures together */
+	pdata = &pstore->pdata;
+	pdata->cam_i2c_board_info = &pstore->i2c_camera;
+	pstore->i2c_camera.platform_data = &pstore->camera_link;
+	pstore->camera_link.priv = &pstore->mt9t111_cam_info;
+
+	ret = of_property_read_string(np, "cssp,camera-clk-name",
+			&pdata->cam_clk_name);
+	if (ret != 0) {
+		dev_err(dev, "No cssp,camera-clk-name property\n");
+		goto err_fail;
+	}
+
+	ret = of_property_read_u32(np, "cssp,camera-clk-rate",
+			&pdata->cam_clk_rate);
+	if (ret != 0) {
+		dev_err(dev, "no cssp,camera-clk-rate property\n");
+		goto err_fail;
+	}
+
+	/* we don't use the dma accessors, but we use the format */
+	ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", 0, &args);
+	if (ret != 0 || args.args_count < 1) {
+		dev_err(dev, "No valid dmas property\n");
+		goto err_fail;
+	}
+	pdata->dma_ch = args.args[0];
+	/* release ref */
+	of_node_put(args.np);
+	args.np = NULL;
+
+	/* can possibly fail */
+	pdata->gpio_reset_pin = of_get_named_gpio(np,
+			"reset-gpio", 0);
+
+	gpio_orientation_pin = of_get_named_gpio(np,
+			"orientation-gpio", 0);
+
+	/* get sensor node */
+	nps = of_get_child_by_name(np, "cssp,sensor");
+	if (nps == NULL) {
+		dev_err(dev, "Failed to get sensor node\n");
+		goto err_fail;
+	}
+
+	/* find the i2c adapter number */
+	npa = of_parse_phandle(nps, "i2c-adapter", 0);
+	if (np == NULL) {
+		dev_err(dev, "Failed to get i2c-adapter property");
+		goto err_fail;
+	}
+	adap = of_find_i2c_adapter_by_node(npa);
+	if (adap == NULL) {
+		dev_err(dev, "Failed to find i2c-adapter");
+		goto err_fail;
+	}
+	pstore->camera_link.i2c_adapter_id = adap->nr;
+
+	/* release i2c adapter device ref */
+	put_device(&adap->dev);
+	adap = NULL;
+
+	/* release i2c adapter device node */
+	of_node_put(npa);
+	npa = NULL;
+
+	/* now find the sensor node */
+	for_each_available_child_of_node(nps, npc) {
+		/* we only support a single sensor for now */
+		if (of_device_is_compatible(npc, "aptina,mt9t112")) {
+			strncpy(pstore->i2c_camera.type, "mt9t112",
+					sizeof(pstore->i2c_camera.type));
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		dev_err(dev, "Failed to find sensor node");
+		goto err_fail;
+	}
+
+	if (of_property_read_u32(npc, "reg", &val) != 0) {
+		dev_err(dev, "Could not get sensor reg property\n");
+		goto err_fail;
+	}
+	pstore->i2c_camera.addr = val;
+
+	if (of_property_read_u32_array(npc, "pll-divider", valarr, ARRAY_SIZE(valarr)) != 0) {
+		dev_err(dev, "Could not get pll-divider property\n");
+		goto err_fail;
+	}
+	pstore->mt9t111_cam_info.divider.m = valarr[0];
+	pstore->mt9t111_cam_info.divider.n = valarr[1];
+	pstore->mt9t111_cam_info.divider.p1 = valarr[2];
+	pstore->mt9t111_cam_info.divider.p2 = valarr[3];
+	pstore->mt9t111_cam_info.divider.p3 = valarr[4];
+	pstore->mt9t111_cam_info.divider.p4 = valarr[5];
+	pstore->mt9t111_cam_info.divider.p5 = valarr[6];
+	pstore->mt9t111_cam_info.divider.p6 = valarr[7];
+	pstore->mt9t111_cam_info.divider.p7 = valarr[8];
+
+	if (of_property_read_u32(npc, "flags", &val) != 0) {
+		dev_err(dev, "Could not get sensor flags property\n");
+		goto err_fail;
+	}
+
+	/* read orientation gpio and set/clr MT9T112_FLAG_VFLIP */
+	if (gpio_is_valid(gpio_orientation_pin)) {
+		ret = gpio_request(gpio_orientation_pin, "camera orientation");
+		if (ret != 0) {
+			dev_err(dev, "Could not gpio_request orientation\n");
+			goto err_fail;
+		}
+		ret = gpio_direction_input(gpio_orientation_pin);
+		if (ret != 0) {
+			dev_err(dev, "Could not set orientation to input\n");
+			gpio_free(gpio_orientation_pin);
+			goto err_fail;
+		}
+		ret = gpio_get_value(gpio_orientation_pin);
+		if (ret < 0) {
+			dev_err(dev, "Could not get orientation value\n");
+			gpio_free(gpio_orientation_pin);
+			goto err_fail;
+		}
+		gpio_free(gpio_orientation_pin);
+
+		/* set orientation flag */
+
+#ifdef MT9T112_FLAG_VFLIP
+	 	if (ret)
+	 		val |= MT9T112_FLAG_VFLIP;
+	 	else
+	 		val &= ~MT9T112_FLAG_VFLIP;
+#endif
+	}
+	pstore->mt9t111_cam_info.flags = val;
+
+	/* release refs */
+
+	of_node_put(npc);
+	npc = NULL;
+	of_node_put(nps);
+	nps = NULL;
+
+	return pdata;
+
+err_fail:
+	/* NULL is handled as a NOP */
+	of_node_put(nps);
+	of_node_put(npc);
+	of_node_put(npa);
+
+	/* release adapter */
+	if (adap != NULL)
+		put_device(&adap->dev);
+
+	/* free memory (even if automatically freed it's good practice) */
+	if (pstore != NULL)
+		devm_kfree(dev, pstore);
+
+	return NULL;
+}
+
+#else
+struct cssp_cam_platform_data *of_get_cssp_platform_data(struct platform_device *pdev)
+{
+	return NULL;
+}
+#endif
+
+static int cssp_cam_probe(struct platform_device *pdev)
+{
+	struct cssp_cam_dev *cam_dev;
+	struct cssp_cam_platform_data *pdata;
+	struct pinctrl *pinctrl;
+	int ret = 0, use_of_pdata = 0;
+	struct rstctl *rctrl;
+
+	rctrl = rstctl_get(&pdev->dev, NULL);
+	if (IS_ERR(rctrl)) {
+		dev_info(&pdev->dev, "Failed to get rstctl; nevermind\n");
+		rctrl = NULL;
+	} else {
+		dev_info(&pdev->dev, "Got rstctl (%s:#%d name %s) label:%s\n",
+				rctrl->rdev->rdesc->name,
+				rctrl->line - rctrl->rdev->rdesc->lines,
+				rctrl->line->name, rctrl->label);
+
+		/* always assert to keep the emmc at reset */
+		rstctl_assert(rctrl);
+	}
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev,
+			"pins are not configured from the driver\n");
+
+	pdata = pdev->dev.platform_data;
+
+	/* if not found, try DT */
+	if (pdata == NULL) {
+		pdata = of_get_cssp_platform_data(pdev);
+		use_of_pdata = pdata != NULL;
+	}
+
+	if (pdata == NULL) {
+		dev_err(&pdev->dev, "missing platform data\n");
+		return -ENODEV;
+	}
+	pdev->dev.platform_data = pdata;
+
+	if (pdata->cam_i2c_board_info == NULL) {
+		dev_err(&pdev->dev, "missing camera i2c board info\n");
+		return -ENODEV;
+	}
+
+	cam_dev = kzalloc(sizeof(*cam_dev), GFP_KERNEL);
+	if (!cam_dev)
+		return -ENOMEM;
+
+	/* keep the pointer of the of pdata storage */
+	if (use_of_pdata)
+		cam_dev->pstore = to_cssp_platform_data_storage(pdata);
+
+	cam_dev->pdev = pdev;
+	platform_set_drvdata(pdev, cam_dev);
+
+	cam_dev->rctrl = rctrl;
+
+	cam_dev->camera_board_info = pdata->cam_i2c_board_info;
+
+	cam_dev->camera_clk = clk_get(&pdev->dev, pdata->cam_clk_name);
+	if (IS_ERR(cam_dev->camera_clk)) {
+		ret = PTR_ERR(cam_dev->camera_clk);
+		dev_err(&pdev->dev, "cannot clk_get %s\n", pdata->cam_clk_name);
+		goto fail0;
+	}
+
+	/* 32MHz */
+	ret = clk_set_rate(cam_dev->camera_clk, pdata->cam_clk_rate);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "failed to set clk rate\n");
+		goto fail1;
+	}
+
+	if (clk_get_rate(cam_dev->camera_clk) != pdata->cam_clk_rate) {
+		dev_err(&pdev->dev, "No accurate clock found\n");
+		goto fail1;
+	}
+
+	ret = configure_cssp(cam_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "configure_cssp failed\n");
+		goto fail1;
+	}
+
+	ret = configure_edma(cam_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "configure_dma failed\n");
+		goto fail2;
+	}
+
+	cam_dev->mode = FMT_2X8_EN | PCLK_POL | HS_EN;	// falling edge
+	if (cam_dev->rev > 3)
+		cam_dev->mode |= LDR_EN;
+
+	ret = configure_camera_sensor(cam_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "camera sensor configuration failed\n");
+		goto fail3;
+	}
+
+	cam_dev->dma_cont_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	if (IS_ERR(cam_dev->dma_cont_ctx)) {
+		ret = PTR_ERR(cam_dev->dma_cont_ctx);
+		goto fail3;
+	}
+
+	ret = video_probe(cam_dev);
+	if (ret)
+		goto fail4;
+
+	cam_dev->spillover = vb2_dma_contig_memops.alloc(cam_dev->dma_cont_ctx,
+		MAX_WIDTH * MAX_HEIGHT * BYTES_PER_PIXEL);
+	if (cam_dev->spillover == NULL) {
+		ret = -ENOMEM;
+		goto fail4;
+	}
+	cam_dev->spillover_dma_addr = vb2_dma_contig_cookie(
+			cam_dev->dma_cont_ctx, cam_dev->spillover);
+
+	dev_info(&pdev->dev, "spillover at %p, size %d, phys 0x%08lx\n",
+		cam_dev->spillover,
+		MAX_WIDTH * MAX_HEIGHT * BYTES_PER_PIXEL,
+		(unsigned long)cam_dev->spillover_dma_addr);
+
+	dev_err(&pdev->dev, "Loaded OK.\n");
+
+	return 0;
+
+fail4:
+	vb2_dma_contig_cleanup_ctx(cam_dev->dma_cont_ctx);
+
+fail3:
+	edma_free_channel(cam_dev->dma_ch);
+fail2:
+	if (gpio_is_valid(cam_dev->reset_pin))
+		gpio_free(cam_dev->reset_pin);
+
+	iounmap(cam_dev->reg_base_virt);
+	release_mem_region(cam_dev->reg_base_phys, cam_dev->reg_size);
+
+fail1:
+	clk_put(cam_dev->camera_clk);
+
+fail0:
+	kfree(cam_dev);
+
+	return ret;
+}
+
+static int cssp_cam_remove(struct platform_device *pdev)
+{
+	struct cssp_cam_dev *cam = platform_get_drvdata(pdev);
+
+	iounmap(cam->reg_base_virt);
+
+	release_mem_region(cam->reg_base_phys, cam->reg_size);
+
+	if (gpio_is_valid(cam->reset_pin))
+		gpio_free(cam->reset_pin);
+
+	if (cam->dma_ch)
+		edma_free_channel(cam->dma_ch);
+
+	video_remove(cam);
+
+	clk_put(cam->camera_clk);
+
+	rstctl_put(cam->rctrl);
+
+	kfree(cam);
+
+	dev_info(&pdev->dev, "removed\n");
+
+	return 0;
+}
+
+
+static struct platform_driver cssp_cam_driver = {
+	.probe		= cssp_cam_probe,
+	.remove		= cssp_cam_remove,
+	.driver		= {
+		.name	= "cssp-camera",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(cssp_camera_of_match),
+	},
+};
+
+module_platform_driver(cssp_cam_driver);
+
+
+/*
+ * Macros sets license, author and description
+ */
+MODULE_LICENSE("GPLv2");
+MODULE_AUTHOR("Dan Aizenstros, Damian Eppel, Przemek Szewczyk");
+MODULE_DESCRIPTION("QuickLogic Camera Interface driver");
+
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index e9f3fb5..408e859 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -22,6 +22,8 @@
 #include <linux/regmap.h>
 #include <linux/mfd/core.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
 #include <linux/input/ti_am335x_tsc.h>
@@ -48,6 +50,32 @@ static const struct regmap_config tscadc_regmap_config = {
 	.val_bits = 32,
 };
 
+void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
+{
+	tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
+}
+EXPORT_SYMBOL_GPL(am335x_tsc_se_update);
+
+void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val)
+{
+	spin_lock(&tsadc->reg_lock);
+	tsadc->reg_se_cache |= val;
+	spin_unlock(&tsadc->reg_lock);
+
+	am335x_tsc_se_update(tsadc);
+}
+EXPORT_SYMBOL_GPL(am335x_tsc_se_set);
+
+void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
+{
+	spin_lock(&tsadc->reg_lock);
+	tsadc->reg_se_cache &= ~val;
+	spin_unlock(&tsadc->reg_lock);
+
+	am335x_tsc_se_update(tsadc);
+}
+EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
+
 static void tscadc_idle_config(struct ti_tscadc_dev *config)
 {
 	unsigned int idleconfig;
@@ -64,26 +92,57 @@ static	int ti_tscadc_probe(struct platform_device *pdev)
 	struct resource		*res;
 	struct clk		*clk;
 	struct mfd_tscadc_board	*pdata = pdev->dev.platform_data;
+	struct device_node	*node = pdev->dev.of_node;
 	struct mfd_cell		*cell;
+	struct property         *prop;
+	const __be32            *cur;
+	u32			val;
 	int			err, ctrl;
 	int			clk_value, clock_rate;
-	int			tsc_wires, adc_channels = 0, total_channels;
+	int			tsc_wires = 0, adc_channels = 0, total_channels;
+	int			readouts = 0;
 
-	if (!pdata) {
+	if (!pdata && !pdev->dev.of_node) {
 		dev_err(&pdev->dev, "Could not find platform data\n");
 		return -EINVAL;
 	}
 
-	if (pdata->adc_init)
-		adc_channels = pdata->adc_init->adc_channels;
+	if (pdev->dev.platform_data) {
+		if (pdata->tsc_init)
+			tsc_wires = pdata->tsc_init->wires;
+
+		if (pdata->adc_init)
+			adc_channels = pdata->adc_init->adc_channels;
+	} else {
+		node = of_get_child_by_name(pdev->dev.of_node, "tsc");
+		of_property_read_u32(node, "ti,wires", &tsc_wires);
+		of_property_read_u32(node, "ti,coordinate-readouts", &readouts);
+
+		node = of_get_child_by_name(pdev->dev.of_node, "adc");
+		of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
+               adc_channels++;
+               if (val > 7) {
+                       dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n",
+                                       val);
+                       return -EINVAL;
+               }
+       }
+	}
 
-	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;
 	}
+	if (total_channels == 0) {
+		dev_err(&pdev->dev, "Need atleast one channel.\n");
+		return -EINVAL;
+	}
+
+	if (readouts * 2 + 2 + adc_channels > 16) {
+		dev_err(&pdev->dev, "Too many step configurations requested\n");
+		return -EINVAL;
+	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -129,6 +188,7 @@ static	int ti_tscadc_probe(struct platform_device *pdev)
 		goto ret;
 	}
 
+	spin_lock_init(&tscadc->reg_lock);
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
 
@@ -160,39 +220,51 @@ static	int ti_tscadc_probe(struct platform_device *pdev)
 
 	/* Set the control register bits */
 	ctrl = CNTRLREG_STEPCONFIGWRT |
-			CNTRLREG_TSCENB |
-			CNTRLREG_STEPID |
-			CNTRLREG_4WIRE;
+			CNTRLREG_STEPID;
+	if (tsc_wires > 0) 
+		ctrl |= CNTRLREG_4WIRE | CNTRLREG_TSCENB;
 	tscadc_writel(tscadc, REG_CTRL, ctrl);
 
 	/* Set register bits for Idle Config Mode */
-	tscadc_idle_config(tscadc);
+	if (tsc_wires > 0) 	
+		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);
 
+	tscadc->used_cells = 0;
+	tscadc->tsc_cell = -1;
+	tscadc->adc_cell = -1;
+
 	/* TSC Cell */
-	cell = &tscadc->cells[TSC_CELL];
-	cell->name = "tsc";
-	cell->platform_data = tscadc;
-	cell->pdata_size = sizeof(*tscadc);
+	if (tsc_wires > 0) {
+		tscadc->tsc_cell = tscadc->used_cells;
+		cell = &tscadc->cells[tscadc->used_cells++];
+		cell->name = "tsc";
+		cell->of_compatible = "ti,ti-tscadc";
+		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);
+	if (adc_channels > 0) {
+		tscadc->adc_cell = tscadc->used_cells;
+		cell = &tscadc->cells[tscadc->used_cells++];
+		cell->name = "tiadc";
+		cell->of_compatible = "ti,ti-tscadc";
+		cell->platform_data = &tscadc;
+		cell->pdata_size = sizeof(tscadc);
+	}
 
 	err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
-			TSCADC_CELLS, NULL, 0, NULL);
+			tscadc->used_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:
@@ -235,11 +307,14 @@ static int tscadc_resume(struct device *dev)
 	pm_runtime_get_sync(dev);
 
 	/* context restore */
-	ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_TSCENB |
-			CNTRLREG_STEPID | CNTRLREG_4WIRE;
+	ctrl = CNTRLREG_STEPCONFIGWRT | CNTRLREG_STEPID;
+	if (tscadc_dev->tsc_cell != -1)
+		ctrl |= CNTRLREG_TSCENB | CNTRLREG_4WIRE;
 	tscadc_writel(tscadc_dev, REG_CTRL, ctrl);
-	tscadc_idle_config(tscadc_dev);
-	tscadc_writel(tscadc_dev, REG_SE, STPENB_STEPENB);
+
+	if (tscadc_dev->tsc_cell != -1) 	
+		tscadc_idle_config(tscadc_dev);
+	am335x_tsc_se_update(tscadc_dev);
 	restore = tscadc_readl(tscadc_dev, REG_CTRL);
 	tscadc_writel(tscadc_dev, REG_CTRL,
 			(restore | CNTRLREG_TSCSSENB));
@@ -256,11 +331,18 @@ static const struct dev_pm_ops tscadc_pm_ops = {
 #define TSCADC_PM_OPS NULL
 #endif
 
+static const struct of_device_id ti_tscadc_dt_ids[] = {
+	{ .compatible = "ti,ti-tscadc", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ti_tscadc_dt_ids);
+
 static struct platform_driver ti_tscadc_driver = {
 	.driver = {
 		.name   = "ti_tscadc",
 		.owner	= THIS_MODULE,
 		.pm	= TSCADC_PM_OPS,
+		.of_match_table = of_match_ptr(ti_tscadc_dt_ids),
 	},
 	.probe	= ti_tscadc_probe,
 	.remove	= ti_tscadc_remove,
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
index b8f4864..818f2cd 100644
--- a/drivers/mfd/tps65217.c
+++ b/drivers/mfd/tps65217.c
@@ -26,6 +26,9 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/interrupt.h>
 
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps65217.h>
@@ -153,6 +156,82 @@ static const struct of_device_id tps65217_of_match[] = {
 	{ /* sentinel */ },
 };
 
+static irqreturn_t tps65217_irq(int irq, void *irq_data)
+{
+        struct tps65217 *tps = irq_data;
+        unsigned int int_reg = 0, status_reg = 0;
+
+        tps65217_reg_read(tps, TPS65217_REG_INT, &int_reg);
+        tps65217_reg_read(tps, TPS65217_REG_STATUS, &status_reg);
+        if (status_reg)
+                dev_dbg(tps->dev, "status now: 0x%X\n", status_reg);
+
+        if (!int_reg)
+                return IRQ_NONE;
+
+        if (int_reg & TPS65217_INT_PBI) {
+                /* Handle push button */
+                dev_dbg(tps->dev, "power button status change\n");
+                input_report_key(tps->pwr_but, KEY_POWER,
+                                status_reg & TPS65217_STATUS_PB);
+                input_sync(tps->pwr_but);
+        }
+        if (int_reg & TPS65217_INT_ACI) {
+                /* Handle AC power status change */
+                dev_dbg(tps->dev, "AC power status change\n");
+                /* Press KEY_POWER when AC not present */
+                input_report_key(tps->pwr_but, KEY_POWER,
+                                ~status_reg & TPS65217_STATUS_ACPWR);
+                input_sync(tps->pwr_but);
+        }
+        if (int_reg & TPS65217_INT_USBI) {
+                /* Handle USB power status change */
+                dev_dbg(tps->dev, "USB power status change\n");
+        }
+
+        return IRQ_HANDLED;
+}
+
+static int tps65217_probe_pwr_but(struct tps65217 *tps)
+{
+	int ret;
+        unsigned int int_reg;
+
+	tps->pwr_but = devm_input_allocate_device(tps->dev);
+	if (!tps->pwr_but) {
+		dev_err(tps->dev,
+			"Failed to allocated pwr_but input device\n");
+		return -ENOMEM;
+	}
+
+	tps->pwr_but->evbit[0] = BIT_MASK(EV_KEY);
+	tps->pwr_but->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
+	tps->pwr_but->name = "tps65217_pwr_but";
+	ret = input_register_device(tps->pwr_but);
+	if (ret) {
+		/* NOTE: devm managed device */
+		dev_err(tps->dev, "Failed to register button device\n");
+		return ret;
+	}
+	ret = devm_request_threaded_irq(tps->dev,
+		tps->irq, NULL, tps65217_irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+		"tps65217", tps);
+	if (ret != 0) {
+		dev_err(tps->dev, "Failed to request IRQ %d\n", tps->irq);
+		return ret;
+	}
+
+	/* enable the power button interrupt */
+	ret = tps65217_reg_read(tps, TPS65217_REG_INT, &int_reg);
+	if (ret < 0) {
+		dev_err(tps->dev, "Failed to read INT reg\n");
+		return ret;
+	}
+	int_reg &= ~TPS65217_INT_PBM;
+	tps65217_reg_write(tps, TPS65217_REG_INT, int_reg, TPS65217_PROTECT_NONE);
+	return 0;
+}
+
 static int tps65217_probe(struct i2c_client *client,
 				const struct i2c_device_id *ids)
 {
@@ -160,10 +239,13 @@ static int tps65217_probe(struct i2c_client *client,
 	unsigned int version;
 	unsigned int chip_id = ids->driver_data;
 	const struct of_device_id *match;
+	struct device_node *node;
 	bool status_off = false;
+	int irq = -1, irq_gpio = -1;
 	int ret;
 
-	if (client->dev.of_node) {
+	node = client->dev.of_node;
+	if (node) {
 		match = of_match_device(tps65217_of_match, &client->dev);
 		if (!match) {
 			dev_err(&client->dev,
@@ -171,8 +253,31 @@ static int tps65217_probe(struct i2c_client *client,
 			return -EINVAL;
 		}
 		chip_id = (unsigned int)match->data;
-		status_off = of_property_read_bool(client->dev.of_node,
+		status_off = of_property_read_bool(node,
 					"ti,pmic-shutdown-controller");
+
+		/* at first try to get irq via OF method */
+		irq = irq_of_parse_and_map(node, 0);
+		if (irq <= 0) {
+			irq = -1;
+			irq_gpio = of_get_named_gpio(node, "irq-gpio", 0);
+			if (irq_gpio >= 0) {
+				/* valid gpio; convert to irq */
+				ret = devm_gpio_request_one(&client->dev,
+					irq_gpio, GPIOF_DIR_IN,
+					"tps65217-gpio-irq");
+				if (ret != 0)
+					dev_warn(&client->dev, "Failed to "
+						"request gpio #%d\n", irq_gpio);
+				irq = gpio_to_irq(irq_gpio);
+				if (irq <= 0) {
+					dev_warn(&client->dev, "Failed to "
+						"convert gpio #%d to irq\n",
+						irq_gpio);
+					irq = -1;
+				}
+			}
+		}
 	}
 
 	if (!chip_id) {
@@ -196,6 +301,18 @@ static int tps65217_probe(struct i2c_client *client,
 		return ret;
 	}
 
+	tps->irq = irq;
+	tps->irq_gpio = irq_gpio;
+
+	/* we got an irq, request it */
+	if (tps->irq >= 0) {
+		ret = tps65217_probe_pwr_but(tps);
+		if (ret < 0) {
+			dev_err(tps->dev, "Failed to probe pwr_but\n");
+			return ret;
+		}
+	}
+
 	ret = mfd_add_devices(tps->dev, -1, tps65217s,
 			      ARRAY_SIZE(tps65217s), NULL, 0, NULL);
 	if (ret < 0) {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b151b7c..3c0cbf6 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -499,6 +499,18 @@ config USB_SWITCH_FSA9480
 	  stereo and mono audio, video, microphone and UART data to use
 	  a common connector port.
 
+config GPEVT
+	tristate "Amazing GPIO DMA Event Test Driver(tm)"
+	depends on TI_EDMA
+	help
+	  Simply amazing!
+
+config GROVE_I2C
+	tristate "Support Grove I2C Motor Driver"
+	depends on OF && I2C
+	help
+	  Say Y here to support a minimal Grove I2C Motor Driver
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
@@ -507,4 +519,6 @@ source "drivers/misc/lis3lv02d/Kconfig"
 source "drivers/misc/carma/Kconfig"
 source "drivers/misc/altera-stapl/Kconfig"
 source "drivers/misc/mei/Kconfig"
+source "drivers/misc/cape/Kconfig"
+
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 2129377..72aef82 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -49,3 +49,6 @@ obj-y				+= carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
 obj-$(CONFIG_ALTERA_STAPL)	+=altera-stapl/
 obj-$(CONFIG_INTEL_MEI)		+= mei/
+obj-$(CONFIG_GPEVT)		+= gpevt.o
+obj-$(CONFIG_GROVE_I2C)		+= grove-i2c.o
+obj-y				+= cape/
diff --git a/drivers/misc/cape/Kconfig b/drivers/misc/cape/Kconfig
new file mode 100644
index 0000000..a2ef85e
--- /dev/null
+++ b/drivers/misc/cape/Kconfig
@@ -0,0 +1,5 @@
+#
+# Capes
+#
+
+source "drivers/misc/cape/beaglebone/Kconfig"
diff --git a/drivers/misc/cape/Makefile b/drivers/misc/cape/Makefile
new file mode 100644
index 0000000..7c4eb96
--- /dev/null
+++ b/drivers/misc/cape/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for cape like devices
+#
+
+obj-y				+= beaglebone/
diff --git a/drivers/misc/cape/beaglebone/Kconfig b/drivers/misc/cape/beaglebone/Kconfig
new file mode 100644
index 0000000..4937577
--- /dev/null
+++ b/drivers/misc/cape/beaglebone/Kconfig
@@ -0,0 +1,41 @@
+#
+# Beaglebone capes
+#
+
+config BEAGLEBONE_PINMUX_HELPER
+	tristate "Beaglebone Pinmux Helper"
+	depends on ARCH_OMAP2PLUS && OF
+	default n
+	help
+	  Say Y here to include support for the pinmux helper
+
+config BEAGLEBONE_IIO_HELPER
+	tristate "Beaglebone AM335x TSCADC Helper"
+	depends on ARCH_OMAP2PLUS && OF && MFD_TI_AM335X_TSCADC
+	default n
+	help
+	  Say Y here to include support for the IIO helper
+
+config CAPE_BEAGLEBONE
+	tristate "Beaglebone cape support"
+	depends on ARCH_OMAP2PLUS && OF && I2C
+	default n
+	select OF_PLUGIN
+	help
+	  Say Y here to include support for beaglebone capes
+
+config CAPE_BEAGLEBONE_GEIGER
+	tristate "Beaglebone Geiger Cape"
+	depends on CAPE_BEAGLEBONE
+	default n
+	help
+	  Say Y here to include support for the Geiger Cape
+
+
+config CAPE_BEAGLEBONE_NIXIE
+	tristate "Beaglebone Nixie Cape"
+	depends on CAPE_BEAGLEBONE
+	default n
+	help
+	  Say Y here to include support for the Nixie Cape
+
diff --git a/drivers/misc/cape/beaglebone/Makefile b/drivers/misc/cape/beaglebone/Makefile
new file mode 100644
index 0000000..e32550d
--- /dev/null
+++ b/drivers/misc/cape/beaglebone/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for beaglebone capes
+#
+
+obj-$(CONFIG_BEAGLEBONE_PINMUX_HELPER)	+= bone-pinmux-helper.o
+obj-$(CONFIG_BEAGLEBONE_IIO_HELPER)	+= bone-iio-helper.o
+
+obj-$(CONFIG_CAPE_BEAGLEBONE)		+= capemgr.o
+obj-$(CONFIG_CAPE_BEAGLEBONE_GEIGER)	+= cape-bone-geiger.o
+obj-$(CONFIG_CAPE_BEAGLEBONE_NIXIE)	+= cape-bone-nixie.o
diff --git a/drivers/misc/cape/beaglebone/bone-iio-helper.c b/drivers/misc/cape/beaglebone/bone-iio-helper.c
new file mode 100644
index 0000000..a919857
--- /dev/null
+++ b/drivers/misc/cape/beaglebone/bone-iio-helper.c
@@ -0,0 +1,243 @@
+/*
+ * Industrial IO helper driver
+ *
+ * Copyright (C) 2013 Matt Ranostay <mranostay@gmail.com>
+ *
+ * Based on original work by
+ *  Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/math64.h>
+#include <linux/input/ti_am335x_tsc.h>
+#include <linux/platform_data/ti_am335x_adc.h>
+#include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/consumer.h>
+
+static const struct of_device_id bone_iio_helper_of_match[] = {
+	{
+		.compatible = "bone-iio-helper",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, bone_iio_helper_of_match);
+
+struct iio_helper_info;
+
+struct iio_helper_chan {
+	struct iio_helper_info *info;
+	int index;
+	const char *vsense_name;
+	unsigned int vsense_scale;
+	struct iio_channel *vsense_channel;
+	struct device_attribute attr;
+	unsigned int attr_created : 1;
+};
+
+#define iio_helper_attr_to_chan(attr) \
+	container_of((attr), struct iio_helper_chan, attr)
+
+struct iio_helper_info {
+	struct platform_device *pdev;
+	int channel_count;
+	struct iio_helper_chan *channel;
+	u32 *scale;
+};
+
+static ssize_t iio_helper_show_mvolts(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct iio_helper_chan *chan = iio_helper_attr_to_chan(attr);
+	int ret, val;
+	u32 mvolts;
+
+	ret = iio_read_channel_raw(chan->vsense_channel, &val);
+	if (ret < 0)
+		return ret;
+
+	/* volts = ((1800 / 4096) * val * scale) = (1.8 * val * scale /4096) */
+	mvolts = div_u64(1800 * chan->vsense_scale * (u64)val, 4096 * 100);
+
+	return sprintf(buf, "%d\n", mvolts);
+}
+
+static int bone_iio_helper_probe(struct platform_device *pdev)
+{
+	struct iio_helper_info *info;
+	struct iio_helper_chan *chan;
+	struct device_node *pnode = pdev->dev.of_node;
+	int i, err;
+
+	/* we only support OF */
+	if (pnode == NULL) {
+		dev_err(&pdev->dev, "No platform of_node!\n");
+		return -ENODEV;
+	}
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (info == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate info\n");
+		err = -ENOMEM;
+		goto err_no_mem;
+	}
+	platform_set_drvdata(pdev, info);
+	info->pdev = pdev;
+
+	err = of_property_count_strings(pnode, "vsense-name");
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed on vsense-name string property\n");
+		goto err_no_vsense;
+	}
+	if (err == 0) {
+		dev_err(&pdev->dev, "vsense-name property is empty\n");
+		err = -EINVAL;
+		goto err_no_vsense;
+	}
+	info->channel_count = err;
+	info->channel = devm_kzalloc(&pdev->dev,
+		info->channel_count * sizeof(*info->channel), GFP_KERNEL);
+	if (info->channel == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate channel array\n");
+		err = -ENOMEM;
+		goto err_no_chan;
+	}
+
+	info->scale = devm_kzalloc(&pdev->dev,
+		info->channel_count * sizeof(*info->scale), GFP_KERNEL);
+	if (info->scale == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate scale array\n");
+		err = -ENOMEM;
+		goto err_no_scale;
+	}
+
+	err = of_property_read_u32_array(pnode, "vsense-scale", info->scale,
+			info->channel_count);
+	if (err != 0) {
+		dev_err(&pdev->dev, "Failed to read vsense-scale array\n");
+		goto err_bad_scale;
+	}
+
+	for (i = 0; i < info->channel_count; i++) {
+
+		chan = &info->channel[i];
+
+		err = of_property_read_string_index(pnode, "vsense-name", i,
+				&chan->vsense_name);
+		if (err != 0) {
+			dev_err(&pdev->dev, "Error on vsense-name #%d\n", i);
+			goto err_bad_chan;
+		}
+
+		chan->vsense_scale = info->scale[i];
+		if (chan->vsense_scale == 0) {
+			dev_err(&pdev->dev, "vsense-sense #%d zero\n", i);
+			err = -EINVAL;
+			goto err_bad_chan;
+		}
+
+		chan->vsense_channel = iio_channel_get(NULL, chan->vsense_name);
+		if (IS_ERR(chan->vsense_channel)) {
+			dev_err(&pdev->dev, "Could not get %s analog input\n",
+						chan->vsense_name);
+			err = PTR_ERR(chan->vsense_channel);
+			chan->vsense_channel = NULL;
+			goto err_bad_chan;
+		}
+
+		chan->attr.attr.name = chan->vsense_name;
+		chan->attr.attr.mode = S_IRUGO;
+		chan->attr.show = iio_helper_show_mvolts;
+		chan->attr.store = NULL;
+
+		err = device_create_file(&pdev->dev, &chan->attr);
+		if (err != 0) {
+			dev_err(&pdev->dev, "Could not create %s attr\n",
+						chan->vsense_name);
+			goto err_bad_chan;
+		}
+		chan->attr_created = 1;
+	}
+
+	dev_info(&pdev->dev, "ready\n");
+
+	return 0;
+err_bad_chan:
+	/* cleanup possible channels allocated */
+	for (i = info->channel_count - 1; i >= 0; i--) {
+		chan = &info->channel[i];
+		if (chan->attr_created)
+			device_remove_file(&pdev->dev, &chan->attr);
+		if (chan->vsense_channel != NULL)
+			iio_channel_release(chan->vsense_channel);
+	}
+err_bad_scale:
+	/* nothing */
+err_no_scale:
+	/* nothing */
+err_no_vsense:
+	/* nothing */
+err_no_chan:
+	/* nothing */
+err_no_mem:
+	return err;
+}
+
+
+static int bone_iio_helper_remove(struct platform_device *pdev)
+{
+	struct iio_helper_info *info = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+	struct iio_helper_chan *chan;
+	int i;
+
+	for (i = info->channel_count - 1; i >= 0; i--) {
+		chan = &info->channel[i];
+		device_remove_file(&pdev->dev, &chan->attr);
+		iio_channel_release(chan->vsense_channel);
+	}
+	devm_kfree(dev, info->scale);
+	devm_kfree(dev, info->channel);
+	devm_kfree(dev, info);
+
+	return 0;
+}
+
+struct platform_driver bone_iio_helper_driver = {
+	.probe		= bone_iio_helper_probe,
+	.remove		= bone_iio_helper_remove,
+	.driver	= {
+		.name		= "bone-iio-helper",
+		.owner		= THIS_MODULE,
+		.of_match_table	= bone_iio_helper_of_match,
+	},
+};
+
+module_platform_driver(bone_iio_helper_driver);
+
+MODULE_AUTHOR("Matt Ranostay");
+MODULE_DESCRIPTION("Beaglebone IIO helper driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bone-iio-helper");
diff --git a/drivers/misc/cape/beaglebone/bone-pinmux-helper.c b/drivers/misc/cape/beaglebone/bone-pinmux-helper.c
new file mode 100644
index 0000000..5074365
--- /dev/null
+++ b/drivers/misc/cape/beaglebone/bone-pinmux-helper.c
@@ -0,0 +1,206 @@
+/*
+ * Pinmux helper driver
+ *
+ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+
+static const struct of_device_id bone_pinmux_helper_of_match[] = {
+	{
+		.compatible = "bone-pinmux-helper",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, bone_pinmux_helper_of_match);
+
+struct pinmux_helper_data {
+	struct pinctrl *pinctrl;
+	char *selected_state_name;
+};
+
+static ssize_t pinmux_helper_show_state(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct pinmux_helper_data *data = platform_get_drvdata(pdev);
+	const char *name;
+
+	name = data->selected_state_name;
+	if (name == NULL || strlen(name) == 0)
+		name = "none";
+	return sprintf(buf, "%s\n", name);
+}
+
+static ssize_t pinmux_helper_store_state(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct pinmux_helper_data *data = platform_get_drvdata(pdev);
+	struct pinctrl_state *state;
+	char *state_name;
+	char *s;
+	int err;
+
+	/* duplicate (as a null terminated string) */
+	state_name = kmalloc(count + 1, GFP_KERNEL);
+	if (state_name == NULL)
+		return -ENOMEM;
+	memcpy(state_name, buf, count);
+	state_name[count] = '\0';
+
+	/* and chop off newline */
+	s = strchr(state_name, '\n');
+	if (s != NULL)
+		*s = '\0';
+
+	/* try to select default state at first (if it exists) */
+	state = pinctrl_lookup_state(data->pinctrl, state_name);
+	if (!IS_ERR(state)) {
+		err = pinctrl_select_state(data->pinctrl, state);
+		if (err != 0)
+			dev_err(dev, "Failed to select state %s\n",
+					state_name);
+	} else {
+		dev_err(dev, "Failed to find state %s\n", state_name);
+		err = PTR_RET(state);
+	}
+
+	if (err == 0) {
+		kfree(data->selected_state_name);
+		data->selected_state_name = state_name;
+	}
+
+	return err ? err : count;
+}
+
+static DEVICE_ATTR(state, S_IWUSR | S_IRUGO,
+		   pinmux_helper_show_state, pinmux_helper_store_state);
+
+static struct attribute *pinmux_helper_attributes[] = {
+	&dev_attr_state.attr,
+	NULL
+};
+
+static const struct attribute_group pinmux_helper_attr_group = {
+	.attrs = pinmux_helper_attributes,
+};
+
+static int bone_pinmux_helper_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct pinmux_helper_data *data;
+	struct pinctrl_state *state;
+	char *state_name;
+	int err;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (data == NULL) {
+		dev_err(dev, "Failed to allocate data\n");
+		err = -ENOMEM;
+		goto err_no_mem;
+	}
+	state_name = kmalloc(strlen(PINCTRL_STATE_DEFAULT) + 1,
+			GFP_KERNEL);
+	if (state_name == NULL) {
+		dev_err(dev, "Failed to allocate state name\n");
+		err = -ENOMEM;
+		goto err_no_mem;
+	}
+	data->selected_state_name = state_name;
+	strcpy(data->selected_state_name, PINCTRL_STATE_DEFAULT);
+
+	platform_set_drvdata(pdev, data);
+
+	data->pinctrl = devm_pinctrl_get(dev);
+	if (IS_ERR(data->pinctrl)) {
+		dev_err(dev, "Failed to get pinctrl\n");
+		err = PTR_RET(data->pinctrl);
+		goto err_no_pinctrl;
+	}
+
+	/* try to select default state at first (if it exists) */
+	state = pinctrl_lookup_state(data->pinctrl,
+			data->selected_state_name);
+	if (!IS_ERR(state)) {
+		err = pinctrl_select_state(data->pinctrl, state);
+		if (err != 0) {
+			dev_err(dev, "Failed to select default state\n");
+			goto err_no_state;
+		}
+	} else {
+		data->selected_state_name = '\0';
+	}
+
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&dev->kobj, &pinmux_helper_attr_group);
+	if (err) {
+		dev_err(dev, "Failed to create sysfs group\n");
+		goto err_no_sysfs;
+	}
+
+	return 0;
+
+err_no_sysfs:
+err_no_state:
+	devm_pinctrl_put(data->pinctrl);
+err_no_pinctrl:
+	devm_kfree(dev, data);
+err_no_mem:
+	return err;
+}
+
+static int bone_pinmux_helper_remove(struct platform_device *pdev)
+{
+	struct pinmux_helper_data *data = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+
+	sysfs_remove_group(&dev->kobj, &pinmux_helper_attr_group);
+	kfree(data->selected_state_name);
+	devm_pinctrl_put(data->pinctrl);
+	devm_kfree(dev, data);
+
+	return 0;
+}
+
+struct platform_driver bone_pinmux_helper_driver = {
+	.probe		= bone_pinmux_helper_probe,
+	.remove		= bone_pinmux_helper_remove,
+	.driver = {
+		.name		= "bone-pinmux-helper",
+		.owner		= THIS_MODULE,
+		.of_match_table	= bone_pinmux_helper_of_match,
+	},
+};
+
+module_platform_driver(bone_pinmux_helper_driver);
+
+MODULE_AUTHOR("Pantelis Antoniou");
+MODULE_DESCRIPTION("Beaglebone pinmux helper driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bone-pinmux-helper");
diff --git a/drivers/misc/cape/beaglebone/cape-bone-geiger.c b/drivers/misc/cape/beaglebone/cape-bone-geiger.c
new file mode 100644
index 0000000..fa57be0
--- /dev/null
+++ b/drivers/misc/cape/beaglebone/cape-bone-geiger.c
@@ -0,0 +1,500 @@
+/*
+ * Driver for beaglebone Geiger cape
+ *
+ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/clkdev.h>
+#include <linux/pwm.h>
+#include <linux/math64.h>
+#include <linux/atomic.h>
+#include <linux/leds.h>
+#include <linux/input/ti_am335x_tsc.h>
+#include <linux/platform_data/ti_am335x_adc.h>
+#include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/consumer.h>
+
+/* fwd decl. */
+struct bone_geiger_info {
+	struct platform_device *pdev;
+	struct pwm_device *pwm_dev;
+	int pwm_frequency;
+	int pwm_duty_cycle;
+	int run;
+	atomic64_t counter;
+	int event_gpio;
+	int event_irq;
+	struct led_trigger *event_led;		/* event detect */
+	struct led_trigger *run_led;		/* running      */
+	unsigned long event_blink_delay;
+	struct sysfs_dirent *counter_sd;	/* notifier */
+	const char *vsense_name;
+	unsigned int vsense_scale;
+	struct iio_channel *vsense_channel;
+};
+
+static const struct of_device_id bonegeiger_of_match[] = {
+	{
+		.compatible = "bone-cape-geiger",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, bonegeiger_of_match);
+
+
+#define	DEFAULT_VSENSE_SCALE	37325		/* 373.25 */
+
+static int bonegeiger_start(struct platform_device *pdev)
+{
+	struct bone_geiger_info *info = platform_get_drvdata(pdev);
+	int duty, period;
+
+	if (info->run != 0)
+		return 0;
+
+	/* checks */
+	if (info->pwm_frequency < 1000 || info->pwm_frequency > 50000) {
+		dev_err(&pdev->dev, "Cowardly refusing to use a "
+				"frequency of %d\n",
+				info->pwm_frequency);
+		return -EINVAL;
+	}
+	if (info->pwm_duty_cycle > 80) {
+		dev_err(&pdev->dev, "Cowardly refusing to use a "
+				"duty cycle of %d\n",
+				info->pwm_duty_cycle);
+		return -EINVAL;
+	}
+
+	period = div_u64(1000000000LLU, info->pwm_frequency);
+	duty = (period * info->pwm_duty_cycle) / 100;
+
+	dev_info(&pdev->dev, "starting geiger tube with "
+			"duty=%duns period=%dus\n",
+			duty, period);
+
+	pwm_config(info->pwm_dev, duty, period);
+	pwm_enable(info->pwm_dev);
+
+	info->run = 1;
+	led_trigger_event(info->run_led, LED_FULL);
+
+	return 0;
+}
+
+static int bonegeiger_stop(struct platform_device *pdev)
+{
+	struct bone_geiger_info *info = platform_get_drvdata(pdev);
+
+	if (info->run == 0)
+		return 0;
+
+	dev_info(&pdev->dev, "disabling geiger tube\n");
+	pwm_config(info->pwm_dev, 0, 50000);	/* 0% duty cycle, 20KHz */
+	pwm_disable(info->pwm_dev);
+
+	info->run = 0;
+	led_trigger_event(info->run_led, LED_OFF);
+
+	return 0;
+}
+
+static ssize_t bonegeiger_show_run(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_geiger_info *info = platform_get_drvdata(pdev);
+
+	return sprintf(buf, "%d\n", info->run);
+}
+
+static ssize_t bonegeiger_store_run(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int run, err;
+
+	if (sscanf(buf, "%i", &run) != 1)
+		return -EINVAL;
+
+	if (run)
+		err = bonegeiger_start(pdev);
+	else
+		err = bonegeiger_stop(pdev);
+
+	return err ? err : count;
+}
+
+static ssize_t bonegeiger_show_counter(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_geiger_info *info = platform_get_drvdata(pdev);
+
+	return sprintf(buf, "%llu\n", atomic64_read(&info->counter));
+}
+
+static ssize_t bonegeiger_store_counter(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_geiger_info *info = platform_get_drvdata(pdev);
+
+	atomic64_set(&info->counter, 0);	/* just reset */
+	return count;
+}
+
+static ssize_t bonegeiger_show_vsense(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_geiger_info *info = platform_get_drvdata(pdev);
+	int ret, val;
+	u32 mvolts;
+
+	ret = iio_read_channel_raw(info->vsense_channel, &val);
+	if (ret < 0)
+		return ret;
+
+	/* V = (1800 / 4096) * val * scale) = (1.8 * val * scale / 4096) */
+	mvolts = div_u64(1800 * info->vsense_scale * (u64)val, 4096 * 100);
+
+	return sprintf(buf, "%d\n", mvolts);
+}
+
+static DEVICE_ATTR(run, S_IRUGO | S_IWUSR,
+		bonegeiger_show_run, bonegeiger_store_run);
+static DEVICE_ATTR(counter, S_IRUGO | S_IWUSR,
+		bonegeiger_show_counter, bonegeiger_store_counter);
+static DEVICE_ATTR(vsense, S_IRUGO,
+		bonegeiger_show_vsense, NULL);
+
+static int bonegeiger_sysfs_register(struct platform_device *pdev)
+{
+	int err;
+
+	err = device_create_file(&pdev->dev, &dev_attr_run);
+	if (err != 0)
+		goto err_no_run;
+
+	err = device_create_file(&pdev->dev, &dev_attr_counter);
+	if (err != 0)
+		goto err_no_counter;
+
+	err = device_create_file(&pdev->dev, &dev_attr_vsense);
+	if (err != 0)
+		goto err_no_vsense;
+
+	return 0;
+
+err_no_vsense:
+	device_remove_file(&pdev->dev, &dev_attr_counter);
+err_no_counter:
+	device_remove_file(&pdev->dev, &dev_attr_run);
+err_no_run:
+	return err;
+}
+
+static void bonegeiger_sysfs_unregister(struct platform_device *pdev)
+{
+	device_remove_file(&pdev->dev, &dev_attr_vsense);
+	device_remove_file(&pdev->dev, &dev_attr_counter);
+	device_remove_file(&pdev->dev, &dev_attr_run);
+}
+
+static irqreturn_t bonegeiger_irq_handler(int irq, void *dev_id)
+{
+	struct platform_device *pdev = dev_id;
+	struct bone_geiger_info *info = platform_get_drvdata(pdev);
+
+	atomic64_inc(&info->counter);
+
+	led_trigger_blink_oneshot(info->event_led,
+		  &info->event_blink_delay, &info->event_blink_delay, 0);
+
+	sysfs_notify_dirent(info->counter_sd);
+
+	return IRQ_HANDLED;
+}
+
+static int bonegeiger_probe(struct platform_device *pdev)
+{
+	struct bone_geiger_info *info;
+	struct pinctrl *pinctrl;
+	struct device_node *pnode = pdev->dev.of_node;
+	phandle phandle;
+	u32 val;
+	int err;
+
+	/* we only support OF */
+	if (pnode == NULL) {
+		dev_err(&pdev->dev, "No platform of_node!\n");
+		return -ENODEV;
+	}
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (info == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate info\n");
+		err = -ENOMEM;
+		goto err_no_mem;
+	}
+	platform_set_drvdata(pdev, info);
+	info->pdev = pdev;
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev,
+			"pins are not configured from the driver\n");
+
+	err = of_property_read_u32(pnode, "pwms", &val);
+	if (err != 0) {
+		dev_err(&pdev->dev, "unable to read pwm handle\n");
+		goto err_no_pwm;
+	}
+	phandle = val;
+
+	info->pwm_dev = of_pwm_request(pnode, NULL);
+	if (IS_ERR(info->pwm_dev)) {
+		dev_err(&pdev->dev, "unable to request PWM\n");
+		err = PTR_ERR(info->pwm_dev);
+		goto err_no_pwm;
+	}
+
+	if (of_property_read_u32(pnode, "pwm-frequency", &val) != 0) {
+		val = 20000;
+		dev_warn(&pdev->dev, "Could not read pwm-frequency property; "
+				"using default %u\n",
+				val);
+	}
+	info->pwm_frequency = val;
+
+	if (of_property_read_u32(pnode, "pwm-duty-cycle", &val) != 0) {
+		val = 60;
+		dev_warn(&pdev->dev, "Could not read pwm-duty-cycle property; "
+				"using default %u\n",
+				val);
+	}
+	info->pwm_duty_cycle = val;
+
+	info->event_gpio = of_get_gpio_flags(pnode, 0, NULL);
+	if (IS_ERR_VALUE(info->event_gpio)) {
+		dev_err(&pdev->dev, "unable to get event GPIO\n");
+		err = info->event_gpio;
+		goto err_no_gpio;
+	}
+
+	err = gpio_request_one(info->event_gpio,
+			GPIOF_DIR_IN | GPIOF_EXPORT,
+			"bone-geiger-cape-event");
+	if (err != 0) {
+		dev_err(&pdev->dev, "failed to request event GPIO\n");
+		goto err_no_gpio;
+	}
+
+	atomic64_set(&info->counter, 0);
+
+	info->event_irq = gpio_to_irq(info->event_gpio);
+	if (IS_ERR_VALUE(info->event_irq)) {
+		dev_err(&pdev->dev, "unable to get event GPIO IRQ\n");
+		err = info->event_irq;
+		goto err_no_irq;
+	}
+
+	err = request_irq(info->event_irq, bonegeiger_irq_handler,
+			IRQF_TRIGGER_RISING | IRQF_SHARED,
+			"bone-geiger-irq", pdev);
+	if (err != 0) {
+		dev_err(&pdev->dev, "unable to request irq\n");
+		goto err_no_irq;
+	}
+
+	err = bonegeiger_sysfs_register(pdev);
+	if (err != 0) {
+		dev_err(&pdev->dev, "unable to register sysfs\n");
+		goto err_no_sysfs;
+	}
+
+	info->counter_sd = sysfs_get_dirent(pdev->dev.kobj.sd, NULL, "counter");
+	if (info->counter_sd == NULL) {
+		dev_err(&pdev->dev, "unable to get dirent of counter\n");
+		err = -ENODEV;
+		goto err_no_counter_dirent;
+	}
+
+	led_trigger_register_simple("geiger-event", &info->event_led);
+	led_trigger_register_simple("geiger-run", &info->run_led);
+
+	led_trigger_event(info->run_led, LED_OFF);
+
+	/* default */
+	if (of_property_read_u32(pnode, "event-blink-delay", &val) != 0) {
+		val = 30;
+		dev_warn(&pdev->dev, "Could not read event-blink-delay "
+				"property; using default %u\n",
+					val);
+	}
+	info->event_blink_delay = val;
+
+	/* default */
+	if (of_property_read_string(pnode, "vsense-name", &info->vsense_name) != 0) {
+		info->vsense_name = "AIN5";
+		dev_warn(&pdev->dev, "Could not read vsense-name property; "
+				"using default '%s'\n",
+					info->vsense_name);
+	}
+
+	if (of_property_read_u32(pnode, "vsense-scale", &info->vsense_scale) != 0) {
+		info->vsense_scale = DEFAULT_VSENSE_SCALE;
+		dev_warn(&pdev->dev, "Could not read vsense-scale property; "
+				"using default %u\n",
+					info->vsense_scale);
+	}
+
+	if (info->vsense_scale == 0) {
+		info->vsense_scale = DEFAULT_VSENSE_SCALE;
+		dev_warn(&pdev->dev, "Invalid vsense-scale property; "
+				"using default %u\n",
+					info->vsense_scale);
+	}
+
+	info->vsense_channel = iio_channel_get(NULL, info->vsense_name);
+	if (IS_ERR(info->vsense_channel)) {
+		dev_err(&pdev->dev, "Could not get %s analog input\n",
+					info->vsense_name);
+		err = PTR_ERR(info->vsense_channel);
+		goto err_no_vsense;
+	}
+
+	dev_info(&pdev->dev, "ready\n");
+
+	err = bonegeiger_start(pdev);
+	if (err != 0) {
+		dev_err(&pdev->dev, "Could not start geiger device\n");
+		goto err_no_start;
+	}
+
+	return 0;
+
+err_no_start:
+	iio_channel_release(info->vsense_channel);
+err_no_vsense:
+	led_trigger_unregister_simple(info->run_led);
+	led_trigger_unregister_simple(info->event_led);
+	sysfs_put(info->counter_sd);
+err_no_counter_dirent:
+	bonegeiger_sysfs_unregister(pdev);
+err_no_sysfs:
+	free_irq(info->event_irq, pdev);
+err_no_irq:
+	gpio_free(info->event_gpio);
+err_no_gpio:
+	pwm_put(info->pwm_dev);
+err_no_pwm:
+	devm_kfree(&pdev->dev, info);
+err_no_mem:
+	return err;
+}
+
+static int bonegeiger_remove(struct platform_device *pdev)
+{
+	struct bone_geiger_info *info = platform_get_drvdata(pdev);
+
+	dev_info(&pdev->dev, "Removing geiger cape driver...\n");
+
+	bonegeiger_stop(pdev);
+
+	iio_channel_release(info->vsense_channel);
+	led_trigger_unregister_simple(info->run_led);
+	led_trigger_unregister_simple(info->event_led);
+	sysfs_put(info->counter_sd);
+	bonegeiger_sysfs_unregister(pdev);
+	free_irq(info->event_irq, pdev);
+	gpio_free(info->event_gpio);
+	pwm_put(info->pwm_dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
+static int bonegeiger_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bonegeiger_info *_dev = platform_get_drvdata(pdev);
+
+	(void)_dev;
+	return 0;
+}
+
+static int bonegeiger_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bonegeiger_info *_dev = platform_get_drvdata(pdev);
+
+	(void)_dev;
+	return 0;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+static struct dev_pm_ops bonegeiger_pm_ops = {
+	SET_RUNTIME_PM_OPS(bonegeiger_runtime_suspend,
+			   bonegeiger_runtime_resume, NULL)
+};
+#define BONEGEIGER_PM_OPS (&bonegeiger_pm_ops)
+#else
+#define BONEGEIGER_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+struct platform_driver bonegeiger_driver = {
+	.probe		= bonegeiger_probe,
+	.remove		= bonegeiger_remove,
+	.driver = {
+		.name		= "bone-cape-geiger",
+		.owner		= THIS_MODULE,
+		.pm		= BONEGEIGER_PM_OPS,
+		.of_match_table	= bonegeiger_of_match,
+	},
+};
+
+module_platform_driver(bonegeiger_driver);
+
+MODULE_AUTHOR("Pantelis Antoniou");
+MODULE_DESCRIPTION("Beaglebone geiger cape");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bone-cape-geiger");
diff --git a/drivers/misc/cape/beaglebone/cape-bone-nixie.c b/drivers/misc/cape/beaglebone/cape-bone-nixie.c
new file mode 100644
index 0000000..7adfdc9
--- /dev/null
+++ b/drivers/misc/cape/beaglebone/cape-bone-nixie.c
@@ -0,0 +1,401 @@
+/*
+ * Driver for beaglebone Nixie cape
+ *
+ *  Copyright (C) 2013 Matt Ranostay <mranostay@gmail.com>
+ *
+ * Based on original work by
+ *  Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
+ *  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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <asm/barrier.h>
+#include <linux/pwm.h>
+#include <linux/leds.h>
+
+enum {
+	BLANK_PWM_CHAN	= 0,
+	BOOST_PWM_CHAN	= 1,
+};
+
+struct bone_nixie_info {
+	struct platform_device *pdev;
+	struct pwm_device *pwm_dev;
+	struct led_trigger *run_led;		/* running */
+
+	int pwm_frequency;
+	int pwm_duty_cycle;
+	int pwm_period;
+	int brightness;
+	int run;
+};
+
+static const struct of_device_id bonenixie_of_match[] = {
+	{
+		.compatible = "bone-cape-nixie",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, bonenixie_of_match);
+
+/*
+ * XXX: PWM subsystem doesn't allow easily selecting multiple channels on
+ *	the same chip... so we hack it.. this shouldn't be here long term
+ */
+
+static void nixie_pwm_config(struct bone_nixie_info *info,
+			     int duty, int chan)
+{
+	struct pwm_device *pwm = info->pwm_dev;
+
+	duty = (info->pwm_period * duty) / 100;
+
+	pwm->hwpwm = chan;
+	pwm_config(pwm, duty, info->pwm_period);
+
+	pwm->chip->ops->enable(pwm->chip, pwm);
+}
+
+static void nixie_pwm_disable(struct pwm_device *pwm, int chan)
+{
+	pwm->hwpwm = chan;
+	pwm->chip->ops->disable(pwm->chip, pwm);
+}
+
+static int bonenixie_start(struct platform_device *pdev)
+{
+	struct bone_nixie_info *info = platform_get_drvdata(pdev);
+	int duty;
+
+	if (info->run != 0)
+		return 0;
+
+	/* checks */
+	if (info->pwm_frequency < 1000 || info->pwm_frequency > 50000) {
+		dev_err(&pdev->dev, "Cowardly refusing to use a "
+				"frequency of %d\n",
+				info->pwm_frequency);
+		return -EINVAL;
+	}
+	if (info->pwm_duty_cycle > 80) {
+		dev_err(&pdev->dev, "Cowardly refusing to use a "
+				"duty cycle of %d\n",
+				info->pwm_duty_cycle);
+		return -EINVAL;
+	}
+
+	info->pwm_period = div_u64(1000000000LLU, info->pwm_frequency);
+	duty = (info->pwm_period * info->pwm_duty_cycle) / 100;
+
+	dev_info(&pdev->dev, "starting nixie tube with "
+			" boost converter duty=%duns period=%dus"
+			" default brightness percent=%d\n",
+			duty, info->pwm_period, info->brightness);
+
+	nixie_pwm_config(info, 100 - info->brightness, BLANK_PWM_CHAN);
+	nixie_pwm_config(info, info->pwm_duty_cycle, BOOST_PWM_CHAN);
+
+	info->run = 1;
+	led_trigger_event(info->run_led, LED_FULL);
+
+	return 0;
+}
+
+static int bonenixie_stop(struct platform_device *pdev)
+{
+	struct bone_nixie_info *info = platform_get_drvdata(pdev);
+
+	if (info->run == 0)
+		return 0;
+
+	dev_info(&pdev->dev, "disabling nixie tube\n");
+
+	nixie_pwm_config(info, 0, BLANK_PWM_CHAN);	/* 0% duty cycle */
+	nixie_pwm_disable(info->pwm_dev, BLANK_PWM_CHAN);
+
+	nixie_pwm_config(info, 0, BOOST_PWM_CHAN);	/* 0% duty cycle */
+	nixie_pwm_disable(info->pwm_dev, BOOST_PWM_CHAN);
+
+	info->run = 0;
+	led_trigger_event(info->run_led, LED_OFF);
+
+	return 0;
+}
+
+static ssize_t bonenixie_show_brightness(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_nixie_info *info = platform_get_drvdata(pdev);
+
+	return sprintf(buf, "%d\n", info->brightness);
+}
+
+
+static ssize_t bonenixie_store_brightness(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_nixie_info *info = platform_get_drvdata(pdev);
+	int brightness;
+
+	if (sscanf(buf, "%d", &brightness) != 1)
+		return -EINVAL;
+
+	if (brightness < 0 || brightness > 100)
+		return -EINVAL;
+
+	info->brightness = brightness;
+	nixie_pwm_config(info, 100 - brightness, BLANK_PWM_CHAN);
+
+	return count;
+}
+
+
+static ssize_t bonenixie_show_run(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_nixie_info *info = platform_get_drvdata(pdev);
+
+	return sprintf(buf, "%d\n", info->run);
+}
+
+
+static ssize_t bonenixie_store_run(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int run, err;
+
+	if (sscanf(buf, "%i", &run) != 1)
+		return -EINVAL;
+
+	if (run)
+		err = bonenixie_start(pdev);
+	else
+		err = bonenixie_stop(pdev);
+
+	return err ? err : count;
+}
+
+static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR,
+		bonenixie_show_brightness, bonenixie_store_brightness);
+
+static DEVICE_ATTR(run, S_IRUGO | S_IWUSR,
+		bonenixie_show_run, bonenixie_store_run);
+
+static int bonenixie_sysfs_register(struct platform_device *pdev)
+{
+	int err;
+
+	err = device_create_file(&pdev->dev, &dev_attr_run);
+	if (err != 0)
+		goto err_no_run;
+
+	err = device_create_file(&pdev->dev, &dev_attr_brightness);
+	if (err != 0)
+		goto err_no_brightness;
+
+	return 0;
+
+err_no_brightness:
+	device_remove_file(&pdev->dev, &dev_attr_run);
+err_no_run:
+	return err;
+}
+
+static void bonenixie_sysfs_unregister(struct platform_device *pdev)
+{
+	device_remove_file(&pdev->dev, &dev_attr_brightness);
+	device_remove_file(&pdev->dev, &dev_attr_run);
+}
+
+static int bonenixie_probe(struct platform_device *pdev)
+{
+	struct bone_nixie_info *info;
+	struct pinctrl *pinctrl;
+	struct device_node *pnode = pdev->dev.of_node;
+	phandle phandle;
+	u32 val;
+	int err;
+
+	/* we only support OF */
+	if (pnode == NULL) {
+		dev_err(&pdev->dev, "No platform of_node!\n");
+		return -ENODEV;
+	}
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (info == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate info\n");
+		err = -ENOMEM;
+		goto err_no_mem;
+	}
+	platform_set_drvdata(pdev, info);
+	info->pdev = pdev;
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev,
+			"pins are not configured from the driver\n");
+
+	err = of_property_read_u32(pnode, "pwms", &val);
+	if (err != 0) {
+		dev_err(&pdev->dev, "unable to read pwm handle\n");
+		goto err_no_pwm;
+	}
+	phandle = val;
+
+	info->pwm_dev = of_pwm_request(pnode, NULL);
+	if (IS_ERR(info->pwm_dev)) {
+		dev_err(&pdev->dev, "unable to request PWM\n");
+		err = PTR_ERR(info->pwm_dev);
+		goto err_no_pwm;
+	}
+
+	if (of_property_read_u32(pnode, "pwm-frequency", &val) != 0) {
+		val = 9250;
+		dev_warn(&pdev->dev, "Could not read pwm-frequency property; "
+				"using default %u\n",
+				val);
+	}
+	info->pwm_frequency = val;
+
+	if (of_property_read_u32(pnode, "pwm-duty-cycle", &val) != 0) {
+		val = 35;
+		dev_warn(&pdev->dev, "Could not read pwm-duty-cycle property; "
+				"using default %u\n",
+				val);
+	}
+	info->pwm_duty_cycle = val;
+
+	if (of_property_read_u32(pnode, "default-brightness", &val) != 0) {
+		val = 80;
+		dev_warn(&pdev->dev, "Could not read default-brightness property; "
+				"using default %u\n",
+				val);
+	}
+	info->brightness = val;
+
+	err = bonenixie_sysfs_register(pdev);
+	if (err != 0) {
+		dev_err(&pdev->dev, "unable to register sysfs\n");
+		goto err_no_sysfs;
+	}
+
+	led_trigger_register_simple("nixie-run", &info->run_led);
+	led_trigger_event(info->run_led, LED_OFF);
+
+	dev_info(&pdev->dev, "ready\n");
+
+	err = bonenixie_start(pdev);
+	if (err != 0) {
+		dev_err(&pdev->dev, "Could not start nixie device\n");
+		goto err_no_start;
+	}
+
+	return 0;
+
+err_no_start:
+	led_trigger_unregister_simple(info->run_led);
+	bonenixie_sysfs_unregister(pdev);
+err_no_sysfs:
+	/* fall-through */
+err_no_pwm:
+	devm_kfree(&pdev->dev, info);
+err_no_mem:
+	return err;
+}
+
+static int bonenixie_remove(struct platform_device *pdev)
+{
+	struct bone_nixie_info *info = platform_get_drvdata(pdev);
+
+	dev_info(&pdev->dev, "Remove nixie cape driver...\n");
+
+	bonenixie_stop(pdev);
+
+	led_trigger_unregister_simple(info->run_led);
+	bonenixie_sysfs_unregister(pdev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
+static int bonenixie_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_nixie_info *_dev = platform_get_drvdata(pdev);
+
+	(void)_dev;
+	return 0;
+}
+
+static int bonenixie_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_nixie_info *_dev = platform_get_drvdata(pdev);
+
+	(void)_dev;
+	return 0;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+static struct dev_pm_ops bonenixie_pm_ops = {
+	SET_RUNTIME_PM_OPS(bonenixie_runtime_suspend,
+			   bonenixie_runtime_resume, NULL)
+};
+#define BONENIXIE_PM_OPS (&bonenixie_pm_ops)
+#else
+#define BONENIXIE_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+
+struct platform_driver bonenixie_driver = {
+	.probe		= bonenixie_probe,
+	.remove		= bonenixie_remove,
+	.driver = {
+		.name		= "bone-cape-nixie",
+		.owner		= THIS_MODULE,
+		.pm		= BONENIXIE_PM_OPS,
+		.of_match_table = bonenixie_of_match,
+	},
+};
+
+module_platform_driver(bonenixie_driver);
+
+MODULE_AUTHOR("Matt Ranostay");
+MODULE_DESCRIPTION("Beaglebone nixie cape");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bone-nixie-cape");
diff --git a/drivers/misc/cape/beaglebone/capemgr.c b/drivers/misc/cape/beaglebone/capemgr.c
new file mode 100644
index 0000000..b1a8b65
--- /dev/null
+++ b/drivers/misc/cape/beaglebone/capemgr.c
@@ -0,0 +1,2196 @@
+/*
+ * TI Beaglebone cape controller
+ *
+ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_i2c.h>
+#include <linux/of_device.h>
+#include <linux/of_fdt.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/firmware.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/memory.h>
+#include <linux/i2c.h>
+#include <linux/i2c/eeprom.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+
+/* extra command line overrides */
+static char *extra_override = NULL;
+module_param(extra_override, charp, 0444);
+MODULE_PARM_DESC(extra_override,
+		"Comma delimited list of PART-NUMBER[:REV] overrides");
+
+/* disabled capes */
+static char *disable_partno = NULL;
+module_param(disable_partno, charp, 0444);
+MODULE_PARM_DESC(disable_partno,
+		"Comma delimited list of PART-NUMBER[:REV] of disabled capes");
+
+/* enable capes */
+static char *enable_partno = NULL;
+module_param(enable_partno, charp, 0444);
+MODULE_PARM_DESC(enable_partno,
+		"Comma delimited list of PART-NUMBER[:REV] of enabled capes");
+
+
+struct bone_capemgr_info;
+
+struct slot_ee_attribute {
+	struct device_attribute devattr;
+	unsigned int field;
+	struct bone_cape_slot *slot;	/* this is filled when instantiated */
+};
+#define to_slot_ee_attribute(x) \
+	container_of((x), struct slot_ee_attribute, devattr)
+
+struct bbrd_ee_attribute {
+	struct device_attribute devattr;
+	unsigned int field;
+};
+#define to_bbrd_ee_attribute(x) \
+	container_of((x), struct bbrd_ee_attribute, devattr)
+
+struct bone_cape_slot {
+	struct list_head	node;
+	struct bone_capemgr_info *info;
+	int			slotno;
+	u32			eeprom_handle;
+	int			eeprom_addr;
+	struct i2c_client	*client;
+	struct memory_accessor	*macc;
+	unsigned int		probed : 1;
+	unsigned int		probe_failed : 1;
+	unsigned int		override : 1;
+	char			text_id[256];
+	char			signature[256];
+	/* quick access */
+	char			board_name[32+1];
+	char 			version[4+1];
+	char 			manufacturer[16+1];
+	char 			part_number[16+1];
+
+	/* attribute group */
+	char			*ee_attr_name;
+	int			ee_attrs_count;
+	struct slot_ee_attribute *ee_attrs;
+	struct attribute	**ee_attrs_tab;
+	struct attribute_group	attrgroup;
+
+	unsigned int		loading : 1;
+	unsigned int		loaded : 1;
+	char			*dtbo;
+	const struct firmware	*fw;
+	struct device_node	*overlay;
+	int			ovinfo_cnt;
+	struct of_overlay_info	*ovinfo;
+
+	/* loader thread */
+	struct task_struct	*loader_thread;
+
+	/* load priority */
+	int priority;
+};
+
+struct bone_capemap {
+	struct list_head node;
+	char *part_number;
+	struct device_node *map_node;
+};
+
+struct bone_baseboard {
+
+	/* from the matched boardmap node */
+	char			*compatible_name;
+
+	/* filled in by reading the eeprom */
+	char			signature[256];
+	char			text_id[64+1];
+
+	/* quick access */
+	char			board_name[8+1];
+	char 			revision[4+1];
+	char 			serial_number[12+1];
+
+	/* access to the eeprom */
+	u32			eeprom_handle;
+	int			eeprom_addr;
+	struct i2c_client	*client;
+	struct memory_accessor	*macc;
+	unsigned int		probed : 1;
+	unsigned int		probe_failed : 1;
+	unsigned int		override : 1;
+};
+
+struct bone_capemgr_info {
+	struct platform_device	*pdev;
+
+	atomic_t next_slot_nr;
+	struct list_head	slot_list;
+	struct mutex		slots_list_mutex;
+
+	int capemaps_nr;
+	struct list_head	capemap_list;
+	struct mutex		capemap_mutex;
+
+	/* baseboard EEPROM data */
+	struct bone_baseboard	baseboard;
+
+	/* wait queue for keeping the priorities straight */
+	wait_queue_head_t	load_wq;
+};
+
+static int bone_slot_fill_override(struct bone_cape_slot *slot,
+		struct device_node *node,
+		const char *part_number, const char *version);
+static struct bone_cape_slot *bone_capemgr_add_slot(
+		struct bone_capemgr_info *info, struct device_node *node,
+		const char *part_number, const char *version);
+static int bone_capemgr_remove_slot_no_lock(struct bone_cape_slot *slot);
+static int bone_capemgr_remove_slot(struct bone_cape_slot *slot);
+static int bone_capemgr_load(struct bone_cape_slot *slot);
+static int bone_capemgr_unload(struct bone_cape_slot *slot);
+
+/* baseboard EEPROM field definition */
+#define BBRD_EE_FIELD_HEADER		0
+#define BBRD_EE_FIELD_BOARD_NAME	1
+#define BBRD_EE_FIELD_REVISION		2
+#define BBRD_EE_FIELD_SERIAL_NUMBER	3
+#define BBRD_EE_FIELD_CONFIG_OPTION	4
+#define BBRD_EE_FILED_RSVD1		5
+#define BBRD_EE_FILED_RSVD2		6
+#define BBRD_EE_FILED_RSVD3		7
+
+/* cape EEPROM field definitions */
+#define CAPE_EE_FIELD_HEADER		0
+#define CAPE_EE_FIELD_EEPROM_REV	1
+#define CAPE_EE_FIELD_BOARD_NAME	2
+#define CAPE_EE_FIELD_VERSION		3
+#define CAPE_EE_FIELD_MANUFACTURER	4
+#define CAPE_EE_FIELD_PART_NUMBER	5
+#define CAPE_EE_FIELD_NUMBER_OF_PINS	6
+#define CAPE_EE_FIELD_SERIAL_NUMBER	7
+#define CAPE_EE_FIELD_PIN_USAGE		8
+#define CAPE_EE_FIELD_VDD_3V3EXP	9
+#define CAPE_EE_FIELD_VDD_5V		10
+#define CAPE_EE_FIELD_SYS_5V		11
+#define CAPE_EE_FIELD_DC_SUPPLIED	12
+#define CAPE_EE_FIELD_FIELDS_NR		13
+
+#define EE_FIELD_MAKE_HEADER(p)	\
+	({ \
+		const u8 *_p = (p); \
+		(((u32)_p[0] << 24) | ((u32)_p[1] << 16) | \
+		( (u32)_p[2] <<  8) |  (u32)_p[3]      ); \
+	})
+
+#define EE_FIELD_HEADER_VALID	0xaa5533ee
+
+struct ee_field {
+	const char 	*name;
+	int 		start;
+	int		size;
+	unsigned int	ascii : 1;
+	unsigned int	strip_trailing_dots : 1;
+	const char	*override;
+};
+
+/* baseboard EEPROM definitions */
+static const struct ee_field bbrd_sig_fields[] = {
+	[BBRD_EE_FIELD_HEADER] = {
+		.name		= "header",
+		.start		= 0,
+		.size		= 4,
+		.ascii		= 0,
+		.override	= "\xaa\x55\x33\xee",	/* AA 55 33 EE */
+	},
+	[BBRD_EE_FIELD_BOARD_NAME] = {
+		.name		= "board-name",
+		.start		= 4,
+		.size		= 8,
+		.ascii		= 1,
+		.strip_trailing_dots = 1,
+		.override	= "Board Name",
+	},
+	[BBRD_EE_FIELD_REVISION] = {
+		.name		= "revision",
+		.start		= 12,
+		.size		= 4,
+		.ascii		= 1,
+		.override	= "00A0",
+	},
+	[BBRD_EE_FIELD_SERIAL_NUMBER] = {
+		.name		= "serial-number",
+		.start		= 16,
+		.size		= 12,
+		.ascii		= 1,
+		.override	= "0000000000",
+	},
+	[BBRD_EE_FIELD_CONFIG_OPTION] = {
+		.name		= "config-option",
+		.start		= 28,
+		.size		= 32,
+	},
+};
+
+/* cape EEPROM definitions */
+static const struct ee_field cape_sig_fields[] = {
+	[CAPE_EE_FIELD_HEADER] = {
+		.name		= "header",
+		.start		= 0,
+		.size		= 4,
+		.ascii		= 0,
+		.override	= "\xaa\x55\x33\xee",	/* AA 55 33 EE */
+	},
+	[CAPE_EE_FIELD_EEPROM_REV] = {
+		.name		= "eeprom-format-revision",
+		.start		= 4,
+		.size		= 2,
+		.ascii		= 1,
+		.override	= "A0",
+	},
+	[CAPE_EE_FIELD_BOARD_NAME] = {
+		.name		= "board-name",
+		.start		= 6,
+		.size		= 32,
+		.ascii		= 1,
+		.strip_trailing_dots = 1,
+		.override	= "Override Board Name",
+	},
+	[CAPE_EE_FIELD_VERSION] = {
+		.name		= "version",
+		.start		= 38,
+		.size		= 4,
+		.ascii		= 1,
+		.override	= "00A0",
+	},
+	[CAPE_EE_FIELD_MANUFACTURER] = {
+		.name		= "manufacturer",
+		.start		= 42,
+		.size		= 16,
+		.ascii		= 1,
+		.strip_trailing_dots = 1,
+		.override	= "Override Manuf",
+	},
+	[CAPE_EE_FIELD_PART_NUMBER] = {
+		.name		= "part-number",
+		.start		= 58,
+		.size		= 16,
+		.ascii		= 1,
+		.strip_trailing_dots = 1,
+		.override	= "Override Part#",
+	},
+	[CAPE_EE_FIELD_NUMBER_OF_PINS] = {
+		.name		= "number-of-pins",
+		.start		= 74,
+		.size		= 2,
+		.ascii		= 0,
+		.override	= NULL,
+	},
+	[CAPE_EE_FIELD_SERIAL_NUMBER] = {
+		.name		= "serial-number",
+		.start		= 76,
+		.size		= 12,
+		.ascii		= 1,
+		.override	= "0000000000",
+	},
+	[CAPE_EE_FIELD_PIN_USAGE] = {
+		.name		= "pin-usage",
+		.start		= 88,
+		.size		= 140,
+		.ascii		= 0,
+		.override	= NULL,
+	},
+	[CAPE_EE_FIELD_VDD_3V3EXP] = {
+		.name		= "vdd-3v3exp",
+		.start		= 228,
+		.size		= 2,
+		.ascii		= 0,
+		.override	= NULL,
+	},
+	[CAPE_EE_FIELD_VDD_5V] = {
+		.name		= "vdd-5v",
+		.start		= 230,
+		.size		= 2,
+		.ascii		= 0,
+		.override	= NULL,
+	},
+	[CAPE_EE_FIELD_SYS_5V] = {
+		.name		= "sys-5v",
+		.start		= 232,
+		.size		= 2,
+		.ascii		= 0,
+		.override	= NULL,
+	},
+	[CAPE_EE_FIELD_DC_SUPPLIED] = {
+		.name		= "dc-supplied",
+		.start		= 234,
+		.size		= 2,
+		.ascii		= 0,
+		.override	= NULL,
+	},
+};
+
+static char *ee_field_get(const struct ee_field *sig_field,
+		const void *data, int field, char *buf, int bufsz)
+{
+	int len;
+
+	/* enough space? */
+	if (bufsz < sig_field->size + sig_field->ascii)
+		return NULL;
+
+	memcpy(buf, (char *)data + sig_field->start, sig_field->size);
+
+	/* terminate ascii field */
+	if (sig_field->ascii)
+		buf[sig_field->size] = '\0';;
+
+	if (sig_field->strip_trailing_dots) {
+		len = strlen(buf);
+		while (len > 1 && buf[len - 1] == '.')
+			buf[--len] = '\0';
+	}
+
+	return buf;
+}
+
+char *bbrd_ee_field_get(const void *data,
+		int field, char *buf, int bufsz)
+{
+	if ((unsigned int)field >= ARRAY_SIZE(bbrd_sig_fields))
+		return NULL;
+
+	return ee_field_get(&bbrd_sig_fields[field], data, field, buf, bufsz);
+}
+
+char *cape_ee_field_get(const void *data,
+		int field, char *buf, int bufsz)
+{
+	if ((unsigned int)field >= ARRAY_SIZE(cape_sig_fields))
+		return NULL;
+
+	return ee_field_get(&cape_sig_fields[field], data, field, buf, bufsz);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id bone_capemgr_of_match[] = {
+	{
+		.compatible = "ti,bone-capemgr",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, bone_capemgr_of_match);
+
+#endif
+
+static int bone_baseboard_scan(struct bone_baseboard *bbrd)
+{
+	struct bone_capemgr_info *info = container_of(bbrd,
+			struct bone_capemgr_info, baseboard);
+	struct memory_accessor *macc = bbrd->macc;
+	const u8 *p;
+	int i, r;
+
+	/* need to read EEPROM? */
+	if (bbrd->probed)
+		goto bbrd_fail_check;
+
+	bbrd->probed = 1;
+
+	if (!bbrd->override) {
+
+		if (macc == NULL || macc->read == NULL) {
+			dev_err(&info->pdev->dev,
+				"bone: No memory accessor for baseboard\n");
+			return -ENODEV;
+		}
+
+		for (i = 0; i < 10; i++) {
+
+			/* perform read */
+			r = macc->read(macc, bbrd->signature,
+					0, sizeof(bbrd->signature));
+
+			if (r == sizeof(bbrd->signature))
+				break;
+
+			dev_info(&info->pdev->dev,
+				"bone: scan failed (%d time)\n", i + 1);
+
+			msleep(500);
+		}
+
+		if (i >= 10) {
+			bbrd->probe_failed = 1;
+			return r >= 0 ? -EINVAL : r;
+		}
+
+	} else
+		dev_info(&info->pdev->dev,
+			"bone: Using override eeprom data for baseboard\n");
+
+	p = bbrd->signature;
+	if (EE_FIELD_MAKE_HEADER(p) != EE_FIELD_HEADER_VALID) {
+		dev_err(&info->pdev->dev, "bone: Invalid signature "
+			"'%08x' at baseboard\n",
+			EE_FIELD_MAKE_HEADER(p));
+		bbrd->probe_failed = 1;
+		return -ENODEV;
+	}
+
+	bbrd_ee_field_get(bbrd->signature,
+			BBRD_EE_FIELD_BOARD_NAME,
+			bbrd->board_name, sizeof(bbrd->board_name));
+	bbrd_ee_field_get(bbrd->signature,
+			BBRD_EE_FIELD_REVISION,
+			bbrd->revision, sizeof(bbrd->revision));
+	bbrd_ee_field_get(bbrd->signature,
+			BBRD_EE_FIELD_SERIAL_NUMBER,
+			bbrd->serial_number, sizeof(bbrd->serial_number));
+
+	/* board_name,version,manufacturer,part_number */
+	snprintf(bbrd->text_id, sizeof(bbrd->text_id) - 1,
+			"%s,%s,%s", bbrd->board_name, bbrd->revision,
+			bbrd->serial_number);
+
+	/* terminate always */
+	bbrd->text_id[sizeof(bbrd->text_id) - 1] = '\0';
+
+bbrd_fail_check:
+	/* bbrd has failed and we don't support hotpluging */
+	if (bbrd->probe_failed)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int bone_slot_scan(struct bone_cape_slot *slot)
+{
+	struct bone_capemgr_info *info = slot->info;
+	struct memory_accessor *macc = slot->macc;
+	const u8 *p;
+	int r;
+
+	/* need to read EEPROM? */
+	if (slot->probed)
+		goto slot_fail_check;
+
+	slot->probed = 1;
+
+	if (!slot->override) {
+
+		if (macc == NULL || macc->read == NULL) {
+			dev_err(&info->pdev->dev,
+				"bone: No memory accessor for slot %d\n",
+				slot->slotno);
+			return -ENODEV;
+		}
+
+		/* perform read */
+		r = macc->read(macc, slot->signature,
+				0, sizeof(slot->signature));
+
+		if (r != sizeof(slot->signature)) {
+			slot->probe_failed = 1;
+			return r >= 0 ? -EINVAL : r;
+		}
+	} else
+		dev_info(&info->pdev->dev,
+			"bone: Using override eeprom data at slot %d\n",
+			slot->slotno);
+
+	p = slot->signature;
+	if (EE_FIELD_MAKE_HEADER(p) != EE_FIELD_HEADER_VALID) {
+		dev_err(&info->pdev->dev, "bone: Invalid signature "
+			"'%08x' at slot %d\n",
+			EE_FIELD_MAKE_HEADER(p),
+			slot->slotno);
+		slot->probe_failed = 1;
+		return -ENODEV;
+	}
+
+	cape_ee_field_get(slot->signature,
+			CAPE_EE_FIELD_BOARD_NAME,
+			slot->board_name, sizeof(slot->board_name));
+	cape_ee_field_get(slot->signature,
+			CAPE_EE_FIELD_VERSION,
+			slot->version, sizeof(slot->version));
+	cape_ee_field_get(slot->signature,
+			CAPE_EE_FIELD_MANUFACTURER,
+			slot->manufacturer, sizeof(slot->manufacturer));
+	cape_ee_field_get(slot->signature,
+			CAPE_EE_FIELD_PART_NUMBER,
+			slot->part_number, sizeof(slot->part_number));
+
+	/* board_name,version,manufacturer,part_number */
+	snprintf(slot->text_id, sizeof(slot->text_id) - 1,
+			"%s,%s,%s,%s", slot->board_name, slot->version,
+			slot->manufacturer, slot->part_number);
+
+	/* terminate always */
+	slot->text_id[sizeof(slot->text_id) - 1] = '\0';
+
+slot_fail_check:
+	/* slot has failed and we don't support hotpluging */
+	if (slot->probe_failed)
+		return -ENODEV;
+
+	return 0;
+}
+
+/* return 0 if not matched,, 1 if matched */
+static int bone_match_cape(const char *match,
+		const char *part_number, const char *version)
+{
+	char *tmp_part_number, *tmp_version;
+	char *buf, *s, *e, *sn;
+	int found;
+
+	if (match == NULL || part_number == NULL)
+		return 0;
+
+	/* copy the argument to work on it */
+	buf = kstrdup(match, GFP_KERNEL);
+
+	/* no memory, too bad... */
+	if (buf == NULL)
+		return 0;
+
+	found = 0;
+	s = buf;
+	e = s + strlen(s);
+	while (s < e) {
+		/* find comma separator */
+		sn = strchr(s, ',');
+		if (sn != NULL)
+			*sn++ = '\0';
+		else
+			sn = e;
+		tmp_part_number = s;
+		tmp_version = strchr(tmp_part_number, ':');
+		if (tmp_version != NULL)
+			*tmp_version++ = '\0';
+		s = sn;
+
+		/* the part names must match */
+		if (strcmp(tmp_part_number, part_number) != 0)
+			continue;
+
+		/* if there's no version, match any */
+		if (version == NULL || tmp_version == NULL ||
+			strcmp(version, tmp_version) == 0) {
+			found = 1;
+			break;
+		}
+	}
+
+	kfree(buf);
+
+	return found;
+}
+
+/* check an override slot node if it's compatible */
+static int bone_is_compatible_override(struct device_node *node,
+		const char *compatible_name)
+{
+	struct property *prop;
+	const char *part_number;
+	const char *version;
+
+	/* check if the slot is compatible with the board */
+	prop = of_find_property(node, "compatible", NULL);
+
+	/* no prop, it's something that's compatible with everything */
+	if (prop == NULL)
+		return 1;
+
+	/* check if it's directly compatible with the baseboard */
+	if (of_multi_prop_cmp(prop, compatible_name) == 0)
+		return 1;
+
+	/* forced override? */
+	if (of_multi_prop_cmp(prop, "force") == 0)
+		return 1;
+
+	/* final try, check if it's specified in the kernel command line */
+	if (extra_override == NULL)
+		return 0;
+
+	/* the compatible name should have kernel-command-line in it */
+	if (of_multi_prop_cmp(prop, "kernel-command-line") != 0)
+		return 0;
+
+	/* we must have at least the part-name */
+	if (of_property_read_string(node, "part-number",
+				&part_number) != 0)
+		return 0;
+
+	/* read the version (if it exists) */
+	if (of_property_read_string(node, "version", &version) != 0)
+		version = NULL;
+
+	/* match on the extra override */
+	return bone_match_cape(extra_override, part_number, version);
+}
+
+static int bone_is_compatible_runtime_override(struct device_node *node,
+		const char *req_part_number, const char *req_version)
+{
+	struct property *prop;
+	const char *part_number;
+	const char *version;
+
+	/* only check overrides */
+	if (!of_property_read_bool(node, "ti,cape-override"))
+		return 0;
+
+	/* check if the slot is compatible with the board */
+	prop = of_find_property(node, "compatible", NULL);
+
+	/* no prop, it's something that's compatible with everything */
+	if (prop == NULL)
+		return 1;
+
+	/* the compatible name should have runtime in it */
+	if (of_multi_prop_cmp(prop, "runtime") != 0)
+		return 0;
+
+	/* we must have at least the part-name */
+	if (of_property_read_string(node, "part-number",
+				&part_number) != 0)
+		return 0;
+
+	/* read the version (if it exists) */
+	if (of_property_read_string(node, "version", &version) != 0)
+		version = NULL;
+
+	/* the part names must match */
+	if (strcmp(req_part_number, part_number) != 0)
+		return 0;
+
+	/* if any version is null, any version matches */
+	if (version == NULL || req_version == NULL)
+		return 1;
+
+	/* finally versions must match */
+	return strcmp(req_version, version) == 0;
+}
+
+
+static ssize_t slot_ee_attr_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct slot_ee_attribute *ee_attr = to_slot_ee_attribute(attr);
+	struct bone_cape_slot *slot = ee_attr->slot;
+	const struct ee_field *sig_field;
+	int i, len;
+	char *p, *s;
+	u16 val;
+
+	/* add newline for ascii fields */
+	sig_field = &cape_sig_fields[ee_attr->field];
+
+	len = sig_field->size + sig_field->ascii;
+	p = kmalloc(len, GFP_KERNEL);
+	if (p == NULL)
+		return -ENOMEM;
+
+	s = cape_ee_field_get(slot->signature, ee_attr->field, p, len);
+	if (s == NULL)
+		return -EINVAL;
+
+	/* add newline for ascii fields and return */
+	if (sig_field->ascii) {
+		len = sprintf(buf, "%s\n", s);
+		goto out;
+	}
+
+	/* case by case handling */
+	switch (ee_attr->field) {
+		case CAPE_EE_FIELD_HEADER:
+			len = sprintf(buf, "%02x %02x %02x %02x\n",
+					s[0], s[1], s[2], s[3]);
+			break;
+
+			/* 2 bytes */
+		case CAPE_EE_FIELD_NUMBER_OF_PINS:
+		case CAPE_EE_FIELD_VDD_3V3EXP:
+		case CAPE_EE_FIELD_VDD_5V:
+		case CAPE_EE_FIELD_SYS_5V:
+		case CAPE_EE_FIELD_DC_SUPPLIED:
+			/* the bone is LE */
+			val = s[0] & (s[1] << 8);
+			len = sprintf(buf, "%u\n", (unsigned int)val & 0xffff);
+			break;
+
+		case CAPE_EE_FIELD_PIN_USAGE:
+
+			len = 0;
+			for (i = 0; i < sig_field->size / 2; i++) {
+				/* the bone is LE */
+				val = s[0] & (s[1] << 8);
+				sprintf(buf, "%04x\n", val);
+				buf += 5;
+				len += 5;
+				s += 2;
+			}
+
+			break;
+
+		default:
+			*buf = '\0';
+			len = 0;
+			break;
+	}
+
+out:
+	kfree(p);
+
+	return len;
+}
+
+#define SLOT_EE_ATTR(_name, _field) \
+	{ \
+		.devattr = __ATTR(_name, 0440, slot_ee_attr_show, NULL), \
+		.field = CAPE_EE_FIELD_##_field , \
+		.slot = NULL, \
+	}
+
+static const struct slot_ee_attribute slot_ee_attrs[] = {
+	SLOT_EE_ATTR(header, HEADER),
+	SLOT_EE_ATTR(eeprom-format-revision, EEPROM_REV),
+	SLOT_EE_ATTR(board-name, BOARD_NAME),
+	SLOT_EE_ATTR(version, VERSION),
+	SLOT_EE_ATTR(manufacturer, MANUFACTURER),
+	SLOT_EE_ATTR(part-number, PART_NUMBER),
+	SLOT_EE_ATTR(number-of-pins, NUMBER_OF_PINS),
+	SLOT_EE_ATTR(serial-number, SERIAL_NUMBER),
+	SLOT_EE_ATTR(pin-usage, PIN_USAGE),
+	SLOT_EE_ATTR(vdd-3v3exp, VDD_3V3EXP),
+	SLOT_EE_ATTR(vdd-5v, VDD_5V),
+	SLOT_EE_ATTR(sys-5v, SYS_5V),
+	SLOT_EE_ATTR(dc-supplied, DC_SUPPLIED),
+};
+
+static int bone_cape_slot_sysfs_register(struct bone_cape_slot *slot)
+{
+	struct bone_capemgr_info *info = slot->info;
+	struct device *dev = &info->pdev->dev;
+	struct slot_ee_attribute *ee_attr;
+	struct attribute_group *attrgroup;
+	int i, err, sz;
+
+	slot->ee_attr_name = kasprintf(GFP_KERNEL, "slot-%d", slot->slotno);
+	if (slot->ee_attr_name == NULL) {
+		dev_err(dev, "slot #%d: Failed to allocate ee_attr_name\n",
+				slot->slotno);
+		err = -ENOMEM;
+		goto err_fail_no_ee_attr_name;
+	}
+
+	slot->ee_attrs_count = ARRAY_SIZE(slot_ee_attrs);
+
+	sz = slot->ee_attrs_count * sizeof(*slot->ee_attrs);
+	slot->ee_attrs = kmalloc(sz, GFP_KERNEL);
+	if (slot->ee_attrs == NULL) {
+		dev_err(dev, "slot #%d: Failed to allocate ee_attrs\n",
+				slot->slotno);
+		err = -ENOMEM;
+		goto err_fail_no_ee_attrs;
+	}
+
+	attrgroup = &slot->attrgroup;
+	memset(attrgroup, 0, sizeof(*attrgroup));
+	attrgroup->name = slot->ee_attr_name;
+
+	sz = sizeof(*slot->ee_attrs_tab) * (slot->ee_attrs_count + 1);
+	attrgroup->attrs = kmalloc(sz, GFP_KERNEL);
+	if (attrgroup->attrs == NULL) {
+		dev_err(dev, "slot #%d: Failed to allocate ee_attrs_tab\n",
+				slot->slotno);
+		err = -ENOMEM;
+		goto err_fail_no_ee_attrs_tab;
+	}
+	/* copy everything over */
+	memcpy(slot->ee_attrs, slot_ee_attrs, sizeof(slot_ee_attrs));
+
+	/* bind this attr to the slot */
+	for (i = 0; i < slot->ee_attrs_count; i++) {
+		ee_attr = &slot->ee_attrs[i];
+		ee_attr->slot = slot;
+		attrgroup->attrs[i] = &ee_attr->devattr.attr;
+	}
+	attrgroup->attrs[i] = NULL;
+
+	err = sysfs_create_group(&dev->kobj, attrgroup);
+	if (err != 0) {
+		dev_err(dev, "slot #%d: Failed to allocate ee_attrs_tab\n",
+				slot->slotno);
+		err = -ENOMEM;
+		goto err_fail_no_ee_attrs_group;
+	}
+
+	return 0;
+
+err_fail_no_ee_attrs_group:
+	kfree(slot->ee_attrs_tab);
+err_fail_no_ee_attrs_tab:
+	kfree(slot->ee_attrs);
+err_fail_no_ee_attrs:
+	kfree(slot->ee_attr_name);
+err_fail_no_ee_attr_name:
+	return err;
+}
+
+static void bone_cape_slot_sysfs_unregister(struct bone_cape_slot *slot)
+{
+	struct bone_capemgr_info *info = slot->info;
+	struct device *dev = &info->pdev->dev;
+
+	sysfs_remove_group(&dev->kobj, &slot->attrgroup);
+	kfree(slot->ee_attrs_tab);
+	kfree(slot->ee_attrs);
+	kfree(slot->ee_attr_name);
+}
+
+static ssize_t bbrd_ee_attr_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct bbrd_ee_attribute *ee_attr = to_bbrd_ee_attribute(attr);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_capemgr_info *info = platform_get_drvdata(pdev);
+	struct bone_baseboard *bbrd = &info->baseboard;
+	const struct ee_field *sig_field;
+	u16 val;
+	int i, len;
+	char *p, *s;
+
+	/* add newline for ascii fields */
+	sig_field = &bbrd_sig_fields[ee_attr->field];
+
+	len = sig_field->size + sig_field->ascii;
+	p = kmalloc(len, GFP_KERNEL);
+	if (p == NULL)
+		return -ENOMEM;
+
+	s = bbrd_ee_field_get(bbrd->signature, ee_attr->field, p, len);
+	if (s == NULL)
+		return -EINVAL;
+
+	/* add newline for ascii fields and return */
+	if (sig_field->ascii) {
+		len = sprintf(buf, "%s\n", s);
+		goto out;
+	}
+
+	/* case by case handling */
+	switch (ee_attr->field) {
+		case BBRD_EE_FIELD_HEADER:
+			len = sprintf(buf, "%02x %02x %02x %02x\n",
+					s[0], s[1], s[2], s[3]);
+			break;
+
+		case BBRD_EE_FIELD_CONFIG_OPTION:
+			len = 0;
+			for (i = 0; i < sig_field->size / 2; i++) {
+				/* the bone is LE */
+				val = s[0] & (s[1] << 8);
+				sprintf(buf, "%04x\n", val);
+				buf += 5;
+				len += 5;
+				s += 2;
+			}
+			break;
+
+		default:
+			*buf = '\0';
+			len = 0;
+			break;
+	}
+
+out:
+	kfree(p);
+
+	return len;
+}
+
+#define BBRD_EE_ATTR(_name, _field) \
+	{ \
+		.devattr = __ATTR(_name, 0440, bbrd_ee_attr_show, NULL), \
+		.field = BBRD_EE_FIELD_##_field , \
+	}
+
+static struct bbrd_ee_attribute bbrd_ee_attrs[] = {
+	BBRD_EE_ATTR(header, HEADER),
+	BBRD_EE_ATTR(board-name, BOARD_NAME),
+	BBRD_EE_ATTR(revision, REVISION),
+	BBRD_EE_ATTR(serial-number, SERIAL_NUMBER),
+	BBRD_EE_ATTR(config-option, CONFIG_OPTION),
+};
+
+static struct attribute *bbrd_attrs_flat[] = {
+	&bbrd_ee_attrs[BBRD_EE_FIELD_HEADER	 	].devattr.attr,
+	&bbrd_ee_attrs[BBRD_EE_FIELD_BOARD_NAME	 	].devattr.attr,
+	&bbrd_ee_attrs[BBRD_EE_FIELD_REVISION		].devattr.attr,
+	&bbrd_ee_attrs[BBRD_EE_FIELD_SERIAL_NUMBER	].devattr.attr,
+	&bbrd_ee_attrs[BBRD_EE_FIELD_CONFIG_OPTION	].devattr.attr,
+	NULL,
+};
+
+static const struct attribute_group bbrd_attr_group = {
+	.name	= "baseboard",
+	.attrs	= bbrd_attrs_flat,
+};
+
+static ssize_t slots_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_capemgr_info *info = platform_get_drvdata(pdev);
+	struct bone_cape_slot *slot;
+	ssize_t len, sz;
+
+	mutex_lock(&info->slots_list_mutex);
+	sz = 0;
+	list_for_each_entry(slot, &info->slot_list, node) {
+
+		len = sprintf(buf, "%2d: %02x:%c%c%c%c%c %s\n",
+				slot->slotno,
+				(int)slot->client ?
+					slot->client->addr & 0x7f : 0xff,
+				slot->probed       ? 'P' : '-',
+				slot->probe_failed ? 'F' : '-',
+				slot->override     ? 'O' : '-',
+				slot->loading	   ? 'l' : '-',
+				slot->loaded	   ? 'L' : '-',
+				slot->text_id);
+
+		buf += len;
+		sz += len;
+	}
+	mutex_unlock(&info->slots_list_mutex);
+
+	return sz;
+}
+
+static ssize_t slots_store(struct device *dev, struct device_attribute *attr,
+		 const char *buf, size_t count)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_capemgr_info *info = platform_get_drvdata(pdev);
+	struct bone_cape_slot *slot;
+	struct device_node *pnode, *node, *slots_node;
+	char *s, *part_number, *version;
+	int ret;
+	int slotno;
+
+	/* check for remove slot */
+	if (strlen(buf) > 0 && buf[0] == '-') {
+		slotno = simple_strtoul(buf + 1, NULL, 10);
+
+		/* now load each (take lock to be sure */
+		mutex_lock(&info->slots_list_mutex);
+		list_for_each_entry(slot, &info->slot_list, node) {
+			if (slotno == slot->slotno)
+				goto found;
+		}
+
+		mutex_unlock(&info->slots_list_mutex);
+		return -ENODEV;
+found:
+		ret = bone_capemgr_remove_slot_no_lock(slot);
+		mutex_unlock(&info->slots_list_mutex);
+
+		if (ret == 0)
+			dev_info(&pdev->dev, "Removed slot #%d\n", slotno);
+		else
+			dev_err(&pdev->dev, "Failed to remove slot #%d\n",
+					slotno);
+
+		return ret == 0 ? strlen(buf) : ret;
+	}
+
+	part_number = kstrdup(buf, GFP_KERNEL);
+	if (part_number == NULL)
+		return -ENOMEM;
+
+	/* remove trailing spaces dots and newlines */
+	s = part_number + strlen(part_number);
+	while (s > part_number &&
+			(isspace(s[-1]) || s[-1] == '\n' || s[-1] == '.'))
+		*--s = '\0';
+
+	version = strchr(part_number, ':');
+	if (version != NULL)
+		*version++ = '\0';
+
+	dev_info(&pdev->dev, "part_number '%s', version '%s'\n",
+			part_number, version ? version : "N/A");
+
+	pnode = pdev->dev.of_node;
+	node = NULL;
+	slot = NULL;
+	ret = 0;
+
+	/* iterate over any slots */
+	slots_node = of_get_child_by_name(pnode, "slots");
+	if (slots_node != NULL) {
+		for_each_child_of_node(slots_node, node) {
+
+			/* check if the override is compatible */
+			if (!bone_is_compatible_runtime_override(node,
+						part_number, version))
+				continue;
+
+			/* if matches the disabled ones skip */
+			if (bone_match_cape(disable_partno,
+						part_number, NULL)) {
+				dev_info(&pdev->dev,
+					"Skipping disabled cape with "
+						"part# %s\n", part_number);
+				continue;
+			}
+
+			slot = bone_capemgr_add_slot(info, node,
+					part_number, version);
+			if (IS_ERR(slot)) {
+				dev_err(&pdev->dev, "Failed to add slot #%d\n",
+					atomic_read(&info->next_slot_nr) - 1);
+				ret = PTR_ERR(slot);
+				slot = NULL;
+				goto err_fail;
+			}
+			break;
+		}
+		of_node_put(node);
+		of_node_put(slots_node);
+	}
+	slots_node = NULL;
+
+	/* no specific slot found, try immediate */
+	if (!slot)
+		slot = bone_capemgr_add_slot(info, NULL,
+				part_number, version);
+
+	if (IS_ERR_OR_NULL(slot)) {
+		dev_err(&pdev->dev, "Failed to add slot #%d\n",
+			atomic_read(&info->next_slot_nr) - 1);
+		ret = slot ? PTR_ERR(slot) : -ENODEV;
+		slot = NULL;
+		goto err_fail;
+	}
+
+	kfree(part_number);
+
+	ret = bone_capemgr_load(slot);
+
+	if (ret != 0)
+		bone_capemgr_remove_slot(slot);
+
+	return ret == 0 ? strlen(buf) : ret;
+err_fail:
+	of_node_put(node);
+	of_node_put(slots_node);
+	kfree(part_number);
+	return ret;
+}
+
+static DEVICE_ATTR(slots, 0644, slots_show, slots_store);
+
+static int bone_capemgr_info_sysfs_register(struct bone_capemgr_info *info)
+{
+	struct device *dev = &info->pdev->dev;
+	int ret;
+
+	ret = device_create_file(dev, &dev_attr_slots);
+	if (ret != 0)
+		goto err_fail_no_slots;
+
+	ret = sysfs_create_group(&dev->kobj, &bbrd_attr_group);
+	if (ret != 0)
+		goto err_fail_no_bbrd_grp;
+
+	return 0;
+err_fail_no_bbrd_grp:
+	device_remove_file(dev, &dev_attr_slots);
+err_fail_no_slots:
+	return ret;
+}
+
+static void bone_capemgr_info_sysfs_unregister(struct bone_capemgr_info *info)
+{
+	struct device *dev = &info->pdev->dev;
+
+	sysfs_remove_group(&dev->kobj, &bbrd_attr_group);
+	device_remove_file(dev, &dev_attr_slots);
+}
+
+/* verify the overlay */
+static int bone_capemgr_verify_overlay(struct bone_cape_slot *slot)
+{
+	struct bone_capemgr_info *info = slot->info;
+	struct device *dev = &info->pdev->dev;
+	struct bone_baseboard *bbrd = &info->baseboard;
+	struct device_node *node = slot->overlay;
+	struct property *prop;
+	struct bone_cape_slot *slotn;
+	int err, counta, countb, i, j;
+	const char *ra, *rb;
+
+	/* validate */
+	if (node == NULL) {
+		dev_err(dev, "slot #%d: No overlay "
+				"for '%s'\n",
+				slot->slotno, slot->part_number);
+		return -EINVAL;
+	}
+
+	/* check if the slot is compatible with the board */
+	prop = of_find_property(node, "compatible", NULL);
+
+	/* no compatible property? */
+	if (prop == NULL) {
+		dev_err(dev, "slot #%d: No compatible property "
+				"for '%s'\n",
+				slot->slotno, slot->part_number);
+		return -EINVAL;
+	}
+
+	/* verify that the cape is baseboard compatible */
+	if (of_multi_prop_cmp(prop, bbrd->compatible_name) != 0) {
+		dev_err(dev, "slot #%d: Incompatible with baseboard "
+				"for '%s'\n",
+				slot->slotno, slot->part_number);
+		return -EINVAL;
+	}
+
+	/* count the strings */
+	counta = of_property_count_strings(node, "exclusive-use");
+	/* no valid property, or no resources; no matter, it's OK */
+	if (counta <= 0)
+		return 0;
+
+	/* and now check if there's a resource conflict */
+	err = 0;
+	mutex_lock(&info->slots_list_mutex);
+	for (i = 0; i < counta; i++) {
+
+		ra = NULL;
+		err = of_property_read_string_index(node, "exclusive-use",
+				i, &ra);
+		if (err != 0) {
+			dev_err(dev, "slot #%d: Could not read string #%d\n",
+					slot->slotno, i);
+			break;
+		}
+
+		list_for_each_entry(slotn, &info->slot_list, node) {
+
+			/* don't check against self */
+			if (slot == slotn)
+				continue;
+
+			/* only check against loaded or loading slots */
+			if (!slotn->loaded && !slotn->loading)
+				continue;
+
+			countb = of_property_count_strings(slotn->overlay,
+					"exclusive-use");
+			/* no valid property, or resources; it's OK */
+			if (countb <= 0)
+				continue;
+
+
+			for (j = 0; j < countb; j++) {
+
+				/* count the resources */
+				rb = NULL;
+				err = of_property_read_string_index(
+					slotn->overlay, "exclusive-use",
+						j, &rb);
+				if (err != 0) {
+					/* error, but we don't care */
+					err = 0;
+					break;
+				}
+
+				/* ignore case; just in case ;) */
+				if (strcasecmp(ra, rb) == 0) {
+
+					/* resource conflict */
+					err = -EEXIST;
+					dev_err(dev, "slot #%d: %s conflict "
+						"%s (#%d:%s)\n", slot->slotno,
+						slot->part_number, ra,
+						slotn->slotno,
+						slotn->part_number);
+					goto out;
+				}
+			}
+		}
+	}
+out:
+	mutex_unlock(&info->slots_list_mutex);
+
+	return err;
+}
+
+static int bone_capemgr_load(struct bone_cape_slot *slot)
+{
+	struct bone_capemgr_info *info = slot->info;
+	struct device *dev = &info->pdev->dev;
+	struct device_node *node;
+	struct property *prop;
+	const char *dtbo;
+	int found, err;
+	struct bone_capemap *capemap;
+
+	if (slot->probe_failed)
+		return -ENODEV;
+
+	if (slot->loaded)
+		return -EAGAIN;
+
+	mutex_lock(&info->capemap_mutex);
+	found = 0;
+	list_for_each_entry(capemap, &info->capemap_list, node) {
+		if (strcmp(capemap->part_number, slot->part_number) == 0) {
+			found = 1;
+			break;
+		}
+	}
+
+	/* found? */
+	if (found) {
+		if (capemap->map_node == NULL) {
+			mutex_unlock(&info->capemap_mutex);
+			/* need to match programatically; not supported yet */
+			dev_err(dev, "slot #%d: Failed to find capemap "
+					"for '%s'\n",
+					slot->slotno, slot->part_number);
+			return -ENODEV;
+		}
+
+		/* locate first match */
+		dtbo = NULL;
+		for_each_child_of_node(capemap->map_node, node) {
+
+			/* dtbo must exist */
+			if (of_property_read_string(node, "dtbo", &dtbo) != 0)
+				continue;
+
+			/* get version property (if any) */
+			prop = of_find_property(node, "version", NULL);
+
+			/* if no version node exists, we match */
+			if (prop == NULL)
+				break;
+
+			if (of_multi_prop_cmp(prop, slot->version) == 0)
+				break;
+		}
+
+		if (node == NULL) {
+			/* can't find dtbo version node? try the default */
+			if (of_property_read_string(capemap->map_node,
+						"dtbo", &dtbo) != 0) {
+				mutex_unlock(&info->capemap_mutex);
+				dev_err(dev, "slot #%d: Failed to find dtbo "
+						"for '%s'\n",
+						slot->slotno,
+						slot->part_number);
+				return -ENODEV;
+			}
+		}
+
+		slot->dtbo = kstrdup(dtbo, GFP_KERNEL);
+		of_node_put(node);	/* handles NULL */
+	} else {
+		dev_info(dev, "slot #%d: Requesting part number/version based "
+				"'%s-%s.dtbo\n",
+				slot->slotno,
+				slot->part_number, slot->version);
+
+		/* no specific capemap node; request the part number + .dtbo*/
+		slot->dtbo = kasprintf(GFP_KERNEL, "%s-%s.dtbo",
+				slot->part_number, slot->version);
+	}
+
+	if (slot->dtbo == NULL) {
+		mutex_unlock(&info->capemap_mutex);
+		dev_err(dev, "slot #%d: Failed to get dtbo '%s'\n",
+				slot->slotno, dtbo);
+		return -ENOMEM;
+	}
+
+	dev_info(dev, "slot #%d: Requesting firmware '%s' for board-name '%s'"
+			", version '%s'\n",
+			slot->slotno,
+			slot->dtbo, slot->board_name, slot->version);
+
+	err = request_firmware(&slot->fw, slot->dtbo, dev);
+	if (err != 0) {
+		dev_err(dev, "failed to load firmware '%s'\n", slot->dtbo);
+		mutex_unlock(&info->capemap_mutex);
+		goto err_fail_no_fw;
+	}
+
+	dev_info(dev, "slot #%d: dtbo '%s' loaded; converting to live tree\n",
+			slot->slotno, slot->dtbo);
+
+	mutex_unlock(&info->capemap_mutex);
+
+	of_fdt_unflatten_tree((void *)slot->fw->data, &slot->overlay);
+	if (slot->overlay == NULL) {
+		dev_err(dev, "slot #%d: Failed to unflatten\n",
+				slot->slotno);
+		err = -EINVAL;
+		goto err_fail;
+	}
+
+	/* mark it as detached */
+	of_node_set_flag(slot->overlay, OF_DETACHED);
+
+	/* perform resolution */
+	err = of_resolve(slot->overlay);
+	if (err != 0) {
+		dev_err(dev, "slot #%d: Failed to resolve tree\n",
+				slot->slotno);
+		goto err_fail;
+	}
+
+	err = bone_capemgr_verify_overlay(slot);
+	if (err != 0) {
+		dev_err(dev, "slot #%d: Failed verification\n",
+				slot->slotno);
+		goto err_fail;
+	}
+
+	/* now build an overlay info array */
+	err = of_build_overlay_info(slot->overlay,
+			&slot->ovinfo_cnt, &slot->ovinfo);
+	if (err != 0) {
+		dev_err(dev, "slot #%d: Failed to build overlay info\n",
+				slot->slotno);
+		goto err_fail;
+	}
+
+	dev_info(dev, "slot #%d: #%d overlays\n",
+			slot->slotno, slot->ovinfo_cnt);
+
+	err = of_overlay(slot->ovinfo_cnt, slot->ovinfo);
+	if (err != 0) {
+		if (err != 0) {
+			dev_err(dev, "slot #%d: Failed to overlay\n",
+					slot->slotno);
+			goto err_fail_overlay;
+		}
+	}
+
+	dev_info(dev, "slot #%d: Applied #%d overlays.\n",
+			slot->slotno, slot->ovinfo_cnt);
+
+	slot->loading = 0;
+	slot->loaded = 1;
+
+	return 0;
+
+err_fail_overlay:
+
+	of_free_overlay_info(slot->ovinfo_cnt, slot->ovinfo);
+	slot->ovinfo_cnt = 0;
+	slot->ovinfo = NULL;
+
+err_fail:
+
+	/* we can't free the overlay, because the unflatten method is a mess */
+	/* __of_free_tree(slot->overlay); */
+	slot->overlay = NULL;
+
+	release_firmware(slot->fw);
+	slot->fw = NULL;
+
+err_fail_no_fw:
+	slot->loading = 0;
+	return err;
+}
+
+static int bone_capemgr_unload(struct bone_cape_slot *slot)
+{
+	if (!slot->loaded || slot->ovinfo == NULL)
+		return -EINVAL;
+
+	of_overlay_revert(slot->ovinfo_cnt, slot->ovinfo);
+
+	slot->ovinfo_cnt = 0;
+	kfree(slot->ovinfo);
+
+	slot->loaded = 0;
+
+	return 0;
+
+}
+
+/* slots_list_mutex must be taken */
+static int bone_capemgr_remove_slot_no_lock(struct bone_cape_slot *slot)
+{
+	struct bone_capemgr_info *info = slot->info;
+	struct device *dev = &info->pdev->dev;
+	int ret;
+
+	if (slot == NULL)
+		return 0;
+
+	if (slot->loaded && slot->ovinfo) {
+		/* unload just in case */
+		ret = bone_capemgr_unload(slot);
+		if (ret != 0) {
+			dev_err(dev, "Unable to unload slot #%d\n", slot->slotno);
+			return ret;
+		}
+	}
+
+	/* if probed OK, remove the sysfs nodes */
+	if (slot->probed && !slot->probe_failed)
+		bone_cape_slot_sysfs_unregister(slot);
+
+	/* remove it from the list */
+	list_del(&slot->node);
+
+	devm_kfree(dev, slot);
+
+	return 0;
+}
+
+static int bone_capemgr_remove_slot(struct bone_cape_slot *slot)
+{
+	struct bone_capemgr_info *info = slot->info;
+	int ret;
+
+	mutex_lock(&info->slots_list_mutex);
+	ret = bone_capemgr_remove_slot_no_lock(slot);
+	mutex_unlock(&info->slots_list_mutex);
+
+	return ret;
+}
+
+static int bone_slot_fill_override(struct bone_cape_slot *slot,
+		struct device_node *node,
+		const char *part_number, const char *version)
+{
+	const struct ee_field *sig_field;
+	struct property *prop;
+	int i, len, has_part_number;
+	u32 val;
+	char *p;
+
+	slot->probe_failed = 0;
+	slot->probed = 0;
+
+	/* zero out signature */
+	memset(slot->signature, 0,
+			sizeof(slot->signature));
+
+	/* first, fill in all with override defaults */
+	for (i = 0; i < ARRAY_SIZE(cape_sig_fields); i++) {
+
+		sig_field = &cape_sig_fields[i];
+
+		/* point to the entry */
+		p = slot->signature + sig_field->start;
+
+		if (sig_field->override)
+			memcpy(p, sig_field->override,
+					sig_field->size);
+		else
+			memset(p, 0, sig_field->size);
+	}
+
+	/* and now, fill any override data from the node */
+	has_part_number = 0;
+	if (node != NULL) {
+		for (i = 0; i < ARRAY_SIZE(cape_sig_fields); i++) {
+
+			sig_field = &cape_sig_fields[i];
+
+			/* find property with the same name (if any) */
+			prop = of_find_property(node, sig_field->name, NULL);
+			if (prop == NULL)
+				continue;
+
+			/* point to the entry */
+			p = slot->signature + sig_field->start;
+
+			/* copy and zero out any remainder */
+			len = prop->length;
+			if (prop->length > sig_field->size)
+				len = sig_field->size;
+			memcpy(p, prop->value, len);
+			if (len < sig_field->size)
+				memset(p + len, 0, sig_field->size - len);
+
+			/* remember if we got a part number which is required */
+			if (i == CAPE_EE_FIELD_PART_NUMBER && len > 0)
+				has_part_number = 1;
+		}
+
+		if (of_property_read_u32(node, "priority", &val) != 0)
+			val = 0;
+		slot->priority = val;
+	}
+
+	/* if a part_number is supplied use it */
+	if (part_number && (len = strlen(part_number)) > 0) {
+		sig_field = &cape_sig_fields[CAPE_EE_FIELD_PART_NUMBER];
+
+		/* point to the entry */
+		p = slot->signature + sig_field->start;
+
+		/* copy and zero out any remainder */
+		if (len > sig_field->size)
+			len = sig_field->size;
+		memcpy(p, part_number, len);
+		if (len < sig_field->size)
+			memset(p + len, 0, sig_field->size - len);
+
+		has_part_number = 1;
+	}
+
+	/* if a version is supplied use it */
+	if (version && (len = strlen(version)) > 0) {
+		sig_field = &cape_sig_fields[CAPE_EE_FIELD_VERSION];
+
+		/* point to the entry */
+		p = slot->signature + sig_field->start;
+
+		/* copy and zero out any remainder */
+		if (len > sig_field->size)
+			len = sig_field->size;
+		memcpy(p, version, len);
+		if (len < sig_field->size)
+			memset(p + len, 0, sig_field->size - len);
+	}
+
+	/* we must have a part number */
+	if (!has_part_number)
+		return -EINVAL;
+
+	slot->override = 1;
+
+	return 0;
+}
+
+static struct bone_cape_slot *
+bone_capemgr_add_slot(struct bone_capemgr_info *info, struct device_node *node,
+		const char *part_number, const char *version)
+{
+	struct device_node *eeprom_node;
+	struct bone_cape_slot *slot;
+	struct device *dev = &info->pdev->dev;
+	int slotno;
+	int ret;
+
+	eeprom_node = NULL;
+
+	slotno = atomic_inc_return(&info->next_slot_nr) - 1;
+
+	slot = devm_kzalloc(dev, sizeof(*slot), GFP_KERNEL);
+	if (slot == NULL) {
+		ret = -ENOMEM;
+		goto err_no_mem;
+	}
+	slot->info = info;
+	slot->slotno = slotno;
+
+	if (node && !of_property_read_bool(node, "ti,cape-override")) {
+		ret = of_property_read_u32(node, "eeprom",
+				&slot->eeprom_handle);
+		if (ret != 0) {
+			dev_err(dev, "slot #%d: failed to locate eeprom\n",
+					slotno);
+			goto err_no_eeprom;
+		}
+		eeprom_node = of_find_node_by_phandle(slot->eeprom_handle);
+		if (eeprom_node == NULL) {
+			dev_err(dev, "slot #%d: failed to find eeprom node\n",
+					slotno);
+			ret = -ENODEV;
+			goto err_no_eeprom_node;
+		}
+		slot->client = of_find_i2c_device_by_node(eeprom_node);
+		if (slot->client == NULL) {
+			dev_err(dev, "slot #%d: failed to find i2c client\n",
+					slotno);
+			ret = -ENODEV;
+			goto err_no_eeprom_client;
+		}
+		/* release ref to the node & get ref of the i2c client */
+		of_node_put(eeprom_node);
+		eeprom_node = NULL;
+		i2c_use_client(slot->client);
+
+		/* grab the memory accessor of the eeprom */
+		slot->macc = i2c_eeprom_get_memory_accessor(slot->client);
+		if (IS_ERR_OR_NULL(slot->macc)) {
+			dev_err(dev, "slot #%d: failed to get "
+					"memory accessor\n", slotno);
+			ret = slot->macc == NULL ? -ENODEV :
+				PTR_ERR(slot->macc);
+			slot->macc = NULL;
+			goto err_no_eeprom_macc;
+		}
+
+	} else {
+		if (node)
+			dev_info(dev, "slot #%d: specific override\n", slotno);
+		else
+			dev_info(dev, "slot #%d: generic override\n", slotno);
+
+		/* fill in everything with defaults first */
+		ret = bone_slot_fill_override(slot, node, part_number, version);
+		if (ret != 0) {
+			dev_err(dev, "slot #%d: override failed\n",
+					slotno);
+			goto err_no_eeprom;
+		}
+	}
+
+	ret = bone_slot_scan(slot);
+	if (ret != 0) {
+
+		if (!slot->probe_failed) {
+			dev_err(dev, "slot #%d: scan failed\n",
+					slotno);
+			goto err_bad_scan;
+		}
+
+		dev_err(dev, "slot #%d: No cape found\n",
+				slotno);
+		/* but all is fine */
+	} else {
+
+		dev_info(dev, "slot #%d: '%s'\n",
+				slotno, slot->text_id);
+
+		ret = bone_cape_slot_sysfs_register(slot);
+		if (ret != 0) {
+			dev_err(dev, "slot #%d: sysfs register failed\n",
+					slotno);
+			goto err_no_sysfs;
+		}
+
+	}
+
+	/* add to the slot list */
+	mutex_lock(&info->slots_list_mutex);
+	list_add_tail(&slot->node, &info->slot_list);
+	mutex_unlock(&info->slots_list_mutex);
+
+	return slot;
+
+err_no_sysfs:
+err_bad_scan:
+err_no_eeprom_macc:
+	i2c_release_client(slot->client);
+err_no_eeprom_client:
+	of_node_put(eeprom_node);	/* handles NULL */
+err_no_eeprom_node:
+	/* nothing */
+err_no_eeprom:
+	devm_kfree(dev, slot);
+
+err_no_mem:
+	return ERR_PTR(ret);
+}
+
+static int lowest_loading_cape(struct bone_cape_slot *slot)
+{
+	struct bone_capemgr_info *info = slot->info;
+	int my_prio = slot->priority;
+	struct device *dev = &info->pdev->dev;
+	int ret;
+
+	dev_info(dev, "loader: check slot-%d %s:%s (prio %d)\n", slot->slotno,
+			slot->part_number, slot->version, slot->priority);
+
+	mutex_lock(&info->slots_list_mutex);
+	ret = 1;
+	list_for_each_entry(slot, &info->slot_list, node) {
+		/* if any slot is loading with lowest priority */
+		if (!slot->loading)
+			continue;
+		if (slot->priority < my_prio) {
+			ret = 0;
+			break;
+		}
+	}
+	mutex_unlock(&info->slots_list_mutex);
+	return ret;
+}
+
+static int bone_capemgr_loader(void *data)
+{
+	struct bone_cape_slot *slot = data;
+	struct bone_capemgr_info *info = slot->info;
+	struct device *dev = &info->pdev->dev;
+	int ret;
+
+	dev_info(dev, "loader: before slot-%d %s:%s (prio %d)\n", slot->slotno,
+			slot->part_number, slot->version, slot->priority);
+
+	/*
+	 * We have a basic priority based arbitration system
+	 * Slots have priorities, so the lower priority ones
+	 * should start loading first. So each time we end up
+	 * here.
+	 */ 
+	ret = wait_event_interruptible(info->load_wq,
+			lowest_loading_cape(slot));
+	if (ret < 0) {
+		dev_info(dev, "loader, Signal pending\n");
+		return ret;
+	}
+
+	dev_info(dev, "loader: after slot-%d %s:%s (prio %d)\n", slot->slotno,
+			slot->part_number, slot->version, slot->priority);
+
+	ret = bone_capemgr_load(slot);
+
+	slot->loading = 0;
+
+	if (ret == 0)
+		dev_info(dev, "loader: done slot-%d %s:%s (prio %d)\n",
+			slot->slotno, slot->part_number, slot->version,
+			slot->priority);
+	else
+		dev_err(dev, "loader: failed to load slot-%d %s:%s (prio %d)\n",
+			slot->slotno, slot->part_number, slot->version,
+			slot->priority);
+
+	/* we're done, wake up all */
+	wake_up_interruptible_all(&info->load_wq);
+
+	/* not loaded? remove */
+	if (ret != 0)
+		bone_capemgr_remove_slot(slot);
+
+	return ret;
+}
+
+static int
+bone_capemgr_probe(struct platform_device *pdev)
+{
+	struct bone_capemgr_info *info;
+	struct bone_baseboard *bbrd;
+	struct bone_cape_slot *slot;
+	struct device_node *pnode = pdev->dev.of_node;
+	struct device_node *baseboardmaps_node;
+	struct device_node *slots_node, *capemaps_node, *node;
+	struct device_node *eeprom_node;
+	const char *part_number;
+	const char *version;
+	const char *board_name;
+	const char *compatible_name;
+	struct bone_capemap *capemap;
+	int ret, len;
+	char *wbuf, *s, *p, *e;
+
+	/* we don't use platform_data at all; we require OF */
+	if (pnode == NULL)
+		return -ENOTSUPP;
+
+	info = devm_kzalloc(&pdev->dev,
+			sizeof(struct bone_capemgr_info), GFP_KERNEL);
+	if (!info) {
+		dev_err(&pdev->dev, "Failed to allocate device structure\n");
+		return -ENOMEM;
+	}
+
+	info->pdev = pdev;
+	platform_set_drvdata(pdev, info);
+
+	atomic_set(&info->next_slot_nr, 0);
+	INIT_LIST_HEAD(&info->slot_list);
+	mutex_init(&info->slots_list_mutex);
+
+	INIT_LIST_HEAD(&info->capemap_list);
+	mutex_init(&info->capemap_mutex);
+
+	init_waitqueue_head(&info->load_wq);
+
+	baseboardmaps_node = NULL;
+	capemaps_node = NULL;
+
+	/* find the baseboard */
+	bbrd = &info->baseboard;
+
+	baseboardmaps_node = of_get_child_by_name(pnode, "baseboardmaps");
+	if (baseboardmaps_node == NULL) {
+		dev_err(&pdev->dev, "Failed to get baseboardmaps node");
+		ret = -ENODEV;
+		goto err_exit;
+	}
+
+	/* get eeprom of the baseboard */
+	ret = of_property_read_u32(pnode, "eeprom",
+			&bbrd->eeprom_handle);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "Failed to locate baseboard eeprom\n");
+		goto err_exit;
+	}
+	eeprom_node = of_find_node_by_phandle(bbrd->eeprom_handle);
+	if (eeprom_node == NULL) {
+		dev_err(&pdev->dev, "Failed to find baseboard eeprom node\n");
+		ret = -ENODEV;
+		goto err_exit;
+	}
+	bbrd->client = of_find_i2c_device_by_node(eeprom_node);
+	of_node_put(eeprom_node);
+	eeprom_node = NULL;
+	if (bbrd->client == NULL) {
+		dev_err(&pdev->dev, "Failed to find baseboard i2c client\n");
+		ret = -ENODEV;
+		goto err_exit;
+	}
+
+	/* release ref to the node & get ref of the i2c client */
+	i2c_use_client(bbrd->client);
+
+	/* grab the memory accessor of the eeprom */
+	bbrd->macc = i2c_eeprom_get_memory_accessor(bbrd->client);
+	if (IS_ERR_OR_NULL(bbrd->macc)) {
+		dev_err(&pdev->dev, "Failed to get "
+				"baseboard memory accessor\n");
+		ret = bbrd->macc == NULL ? -ENODEV :
+			PTR_ERR(bbrd->macc);
+		bbrd->macc = NULL;
+		goto err_exit;
+	}
+
+	ret = bone_baseboard_scan(bbrd);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "Failed to scan baseboard eeprom\n");
+		goto err_exit;
+	}
+
+	dev_info(&pdev->dev, "Baseboard: '%s'\n", bbrd->text_id);
+
+	board_name = NULL;
+	compatible_name = NULL;
+	for_each_child_of_node(baseboardmaps_node, node) {
+		/* there must be board-name */
+		if (of_property_read_string(node, "board-name",
+					&board_name) != 0 ||
+		    of_property_read_string(node, "compatible-name",
+					&compatible_name) != 0)
+			continue;
+
+		if (strcmp(bbrd->board_name, board_name) == 0)
+			break;
+	}
+	of_node_put(baseboardmaps_node);
+	baseboardmaps_node = NULL;
+
+	if (node == NULL) {
+		dev_err(&pdev->dev, "Failed to find compatible map for %s\n",
+				bbrd->board_name);
+		ret = -ENODEV;
+		goto err_exit;
+	}
+	bbrd->compatible_name = kstrdup(compatible_name, GFP_KERNEL);
+	if (bbrd->compatible_name == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate compatible name\n");
+		ret = -ENOMEM;
+		goto err_exit;
+	}
+	of_node_put(node);
+
+	dev_info(&pdev->dev, "compatible-baseboard=%s\n",
+			bbrd->compatible_name);
+
+	/* iterate over any capemaps */
+	capemaps_node = of_get_child_by_name(pnode, "capemaps");
+	if (capemaps_node != NULL) {
+
+		for_each_child_of_node(capemaps_node, node) {
+
+			/* there must be part-number */
+			if (of_property_read_string(node, "part-number",
+						&part_number) != 0)
+				continue;
+
+			/* if matches the disabled ones skip */
+			if (bone_match_cape(disable_partno,
+						part_number, NULL)) {
+				dev_info(&pdev->dev,
+					"Skipping disabled cape with "
+						"part# %s\n", part_number);
+				continue;
+			}
+
+			len = sizeof(*capemap) + strlen(part_number) + 1;
+			capemap = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
+			if (capemap == NULL) {
+				dev_err(&pdev->dev, "Failed to allocate "
+						"capemap\n");
+				ret = -ENOMEM;
+				goto err_exit;
+			}
+			capemap->part_number = (char *)(capemap + 1);
+			capemap->map_node = of_node_get(node);
+			strcpy(capemap->part_number, part_number);
+
+			/* add to the slot list */
+			mutex_lock(&info->capemap_mutex);
+			list_add_tail(&capemap->node, &info->capemap_list);
+			info->capemaps_nr++;
+			mutex_unlock(&info->capemap_mutex);
+		}
+		of_node_put(capemaps_node);
+		capemaps_node = NULL;
+	}
+
+	/* iterate over any slots */
+	slots_node = of_get_child_by_name(pnode, "slots");
+	if (slots_node != NULL) {
+		for_each_child_of_node(slots_node, node) {
+
+			/* check if the override is compatible */
+			if (!bone_is_compatible_override(node,
+						bbrd->compatible_name))
+				continue;
+
+			slot = bone_capemgr_add_slot(info, node,
+					NULL, NULL);
+			if (IS_ERR(slot)) {
+				dev_err(&pdev->dev, "Failed to add slot #%d\n",
+					atomic_read(&info->next_slot_nr));
+				ret = PTR_ERR(slot);
+				goto err_exit;
+			}
+			/* note that slot may be NULL (means it was disabled) */
+		}
+		of_node_put(slots_node);
+	}
+	slots_node = NULL;
+
+	/* iterate over enable_partno (if there) */
+	if (enable_partno && strlen(enable_partno) > 0) {
+
+		/* allocate a temporary buffer */
+		wbuf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL);
+		if (wbuf == NULL) {
+			dev_err(&pdev->dev, "Failed to allocate temporary buffer\n");
+			ret = -ENOMEM;
+			goto err_exit;
+		}
+
+		/* add any enable_partno capes */
+		s = enable_partno;
+		while (*s) {
+			/* form is PART[:REV],PART.. */
+			p = strchr(s, ',');
+			if (p == NULL)
+				e = s + strlen(s);
+			else
+				e = p;
+
+			/* copy to temp buffer */
+			len = e - s;
+			if (len >= PAGE_SIZE - 1)
+				len = PAGE_SIZE - 1;
+			memcpy(wbuf, s, len);
+			wbuf[len] = '\0';
+
+			/* move to the next */
+			s = *e ? e + 1 : e;
+
+			/* now split the rev part */
+			p = strchr(wbuf, ':');
+			if (p != NULL)
+				*p++ = '\0';
+			
+			part_number = wbuf;
+			version = p;
+
+			dev_info(&pdev->dev, "enabled_partno part_number '%s', version '%s'\n",
+					part_number, version ? version : "N/A");
+
+			/* only immediate slots are allowed here */
+			slot = bone_capemgr_add_slot(info, NULL,
+					part_number, version);
+
+			/* we continue even in case of an error */
+			if (IS_ERR_OR_NULL(slot)) {
+				dev_warn(&pdev->dev, "Failed to add slot #%d\n",
+					atomic_read(&info->next_slot_nr) - 1);
+			}
+		}
+
+		devm_kfree(&pdev->dev, wbuf);
+	}
+
+	pm_runtime_enable(&pdev->dev);
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(&pdev->dev, "Failed to pm_runtime_get_sync()\n");
+		goto err_exit;
+	}
+
+	pm_runtime_put(&pdev->dev);
+
+	bone_capemgr_info_sysfs_register(info);
+
+	/* now load each (take lock to be sure */
+	mutex_lock(&info->slots_list_mutex);
+
+	list_for_each_entry(slot, &info->slot_list, node) {
+
+		/* if matches the disabled ones skip */
+		if (bone_match_cape(disable_partno,
+					slot->part_number, NULL)) {
+			dev_info(&pdev->dev,
+				"Skipping loading of disabled cape with "
+					"part# %s\n", slot->part_number);
+			continue;
+		}
+
+		if (!slot->probe_failed && !slot->loaded)
+			slot->loading = 1;
+	}
+
+	/* now start the loader thread(s) (all at once) */
+	list_for_each_entry(slot, &info->slot_list, node) {
+
+		if (!slot->loading)
+			continue;
+
+		slot->loader_thread = kthread_run(bone_capemgr_loader,
+				slot, "capemgr-loader-%d",
+				slot->slotno);
+		if (IS_ERR(slot->loader_thread)) {
+			dev_warn(&pdev->dev, "slot #%d: Failed to "
+					"start loader\n", slot->slotno);
+			slot->loader_thread = NULL;
+		}
+	}
+	mutex_unlock(&info->slots_list_mutex);
+
+	dev_info(&pdev->dev, "initialized OK.\n");
+
+	return 0;
+
+err_exit:
+	of_node_put(baseboardmaps_node);
+	of_node_put(capemaps_node);
+	platform_set_drvdata(pdev, NULL);
+	devm_kfree(&pdev->dev, info);
+
+	return ret;
+}
+
+static int bone_capemgr_remove(struct platform_device *pdev)
+{
+	struct bone_capemgr_info *info = platform_get_drvdata(pdev);
+	struct bone_cape_slot *slot, *slotn;
+	int ret;
+
+	mutex_lock(&info->slots_list_mutex);
+	list_for_each_entry_safe(slot, slotn, &info->slot_list, node)
+		bone_capemgr_remove_slot_no_lock(slot);
+	mutex_unlock(&info->slots_list_mutex);
+
+	bone_capemgr_info_sysfs_unregister(info);
+
+	platform_set_drvdata(pdev, NULL);
+
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	pm_runtime_put(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	devm_kfree(&pdev->dev, info);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
+static int bone_capemgr_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_capemgr_info *_dev = platform_get_drvdata(pdev);
+
+	(void)_dev;
+	return 0;
+}
+
+static int bone_capemgr_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bone_capemgr_info *_dev = platform_get_drvdata(pdev);
+
+	(void)_dev;
+	return 0;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+static struct dev_pm_ops bone_capemgr_pm_ops = {
+	SET_RUNTIME_PM_OPS(bone_capemgr_runtime_suspend,
+			   bone_capemgr_runtime_resume, NULL)
+};
+#define BONE_CAPEMGR_PM_OPS (&bone_capemgr_pm_ops)
+#else
+#define BONE_CAPEMGR_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver bone_capemgr_driver = {
+	.probe		= bone_capemgr_probe,
+	.remove		= bone_capemgr_remove,
+	.driver		= {
+		.name	= "bone-capemgr",
+		.owner	= THIS_MODULE,
+		.pm	= BONE_CAPEMGR_PM_OPS,
+		.of_match_table = of_match_ptr(bone_capemgr_of_match),
+	},
+};
+
+module_platform_driver(bone_capemgr_driver);
+
+MODULE_AUTHOR("Pantelis Antoniou");
+MODULE_DESCRIPTION("Beaglebone cape manager");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bone_capemgr");
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 2baeec5..40b1a95 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -23,6 +23,7 @@
 #include <linux/of.h>
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
+#include <linux/i2c/eeprom.h>
 
 /*
  * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable.
@@ -672,6 +673,27 @@ static int at24_remove(struct i2c_client *client)
 	return 0;
 }
 
+static int at24_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+	struct at24_data *at24;
+	const struct memory_accessor **maccp;
+
+	/* only supporting a single command */
+	if (cmd != I2C_EEPROM_GET_MEMORY_ACCESSOR)
+		return -ENOTSUPP;
+
+	/* rudimentary check */
+	if (arg == NULL)
+		return -EINVAL;
+
+	at24 = i2c_get_clientdata(client);
+
+	maccp = arg;
+	*maccp = &at24->macc;
+
+	return 0;
+}
+
 /*-------------------------------------------------------------------------*/
 
 static struct i2c_driver at24_driver = {
@@ -682,6 +704,7 @@ static struct i2c_driver at24_driver = {
 	.probe = at24_probe,
 	.remove = at24_remove,
 	.id_table = at24_ids,
+	.command = at24_command,
 };
 
 static int __init at24_init(void)
diff --git a/drivers/misc/gpevt.c b/drivers/misc/gpevt.c
new file mode 100644
index 0000000..aabcd48
--- /dev/null
+++ b/drivers/misc/gpevt.c
@@ -0,0 +1,172 @@
+/*
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+
+#define GPEVT_MAGIC 0xdeadbeef
+
+static u32 *dst_fifo;
+static	dma_addr_t fifo_addr;
+
+static void gpevt_callback(void *data)
+{
+	struct device *dev = data;
+
+	dma_unmap_single(dev, fifo_addr, 32, DMA_FROM_DEVICE);
+
+	if (*dst_fifo == GPEVT_MAGIC)
+		dev_info(dev, "*** DMA transfer succeeded ***\n");
+	else
+		dev_info(dev, "*** DMA transfer failed ***\n");
+}
+
+static int gpevt_probe (struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct pinctrl *pinctrl;
+	struct dma_chan *chan;
+	struct dma_slave_config cfg;
+	struct dma_async_tx_descriptor *tx;
+	int gpio_evt = 0;
+	int ret;
+	u32 *src_buf;
+	struct scatterlist sg;
+
+	src_buf = devm_kzalloc(&pdev->dev, 32, GFP_KERNEL);
+	if (!src_buf) {
+		dev_err(&pdev->dev, "failed to allocate src buffer\n");
+		return -ENOMEM;
+	}
+
+	dst_fifo = devm_kzalloc(&pdev->dev, 32, GFP_KERNEL);
+	if (!dst_fifo) {
+		dev_err(&pdev->dev, "failed to allocate dst fifo\n");
+		return -ENOMEM;
+	}
+		
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev,
+			"pins are not configured from the driver\n");
+
+        gpio_evt = of_get_named_gpio(np, "gpio-evt", 0);
+	if (gpio_evt < 0) {
+		dev_err(&pdev->dev, "failed to find gpio event signal!\n");
+		return -EINVAL;
+	}
+
+        ret = devm_gpio_request_one(&pdev->dev, gpio_evt,
+				    GPIOF_IN, "GPIO Event Pin");
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to claim gpio-evt pin\n");
+		return ret;
+	}
+
+	ret = request_irq(gpio_to_irq(gpio_evt), no_action,
+			  IRQ_TYPE_EDGE_FALLING, "gpevt", &pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to request falling edge irq/event\n");
+		return ret;
+	}
+
+	chan = dma_request_slave_channel(&pdev->dev, "gpioevt");
+	if (!chan) {
+		dev_err(&pdev->dev, "no gpio channel for gpevt\n");
+		return -EAGAIN;
+	}
+
+	fifo_addr = dma_map_single(&pdev->dev, dst_fifo, 32, DMA_FROM_DEVICE);
+	if (!fifo_addr) {
+		dev_err(&pdev->dev, "could not map dst fifo\n");
+		return -EIO;
+	}
+	cfg.dst_addr = fifo_addr;
+	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.dst_maxburst = 1;
+
+	ret = dmaengine_slave_config(chan, &cfg);
+	if (ret)
+		return ret;
+
+	*src_buf = GPEVT_MAGIC;
+	sg_init_table(&sg, 1);
+	sg_dma_address(&sg) = dma_map_single(&pdev->dev, src_buf, 32, DMA_TO_DEVICE);
+	sg_dma_len(&sg) = 4;
+
+	tx = dmaengine_prep_slave_sg(chan, &sg, 1, DMA_MEM_TO_DEV,
+				     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!tx) {
+		dev_err(&pdev->dev, "prep_slave_sg() failed\n");
+		return -EIO;
+	}
+
+	tx->callback = gpevt_callback;
+	tx->callback_param = &pdev->dev;
+	dmaengine_submit(tx);
+
+	dma_async_issue_pending(chan);
+		
+	dev_info(&pdev->dev, "Amazing GPIO DMA Event Test Driver(tm) engaged\n");
+
+	return 0;
+}
+
+static int gpevt_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id gpevt_dt_ids[] = {
+	{ .compatible = "gpevt", .data = (void *) NULL, },
+};
+MODULE_DEVICE_TABLE(of, gpevt_dt_ids);
+
+static struct platform_driver gpevt_driver = {
+	.driver = {
+		.name   = "gpevt",
+		.owner  = THIS_MODULE,
+		.of_match_table = gpevt_dt_ids,
+	},
+	.probe  = gpevt_probe,
+	.remove = gpevt_remove,
+};
+
+static int __init gpevt_init(void)
+{
+	return platform_driver_register(&gpevt_driver);
+}
+
+static void __exit gpevt_exit(void)
+{
+	platform_driver_unregister(&gpevt_driver);
+}
+
+/* ------------------------------------------------------------------------- */
+
+module_init(gpevt_init);
+module_exit(gpevt_exit);
+
+MODULE_DESCRIPTION("Amazing GPIO DMA Event Test Driver(tm)");
+MODULE_AUTHOR("Matt Porter <mporter@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/grove-i2c.c b/drivers/misc/grove-i2c.c
new file mode 100644
index 0000000..8932616
--- /dev/null
+++ b/drivers/misc/grove-i2c.c
@@ -0,0 +1,239 @@
+/*
+ *  grove-i2c.c - I2C driver module for the Grove motor drivers
+ *
+ *  Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+
+struct grove_data {
+	struct i2c_client *client;
+	struct mutex lock;
+
+	int state[2];
+#define GS_NONE			0
+#define GS_SOLENOID_FORWARD	1
+#define GS_SOLENOID_BACKWARD	2
+
+};
+
+static void grove_send_word(struct grove_data *data, u8 cmd, u16 val)
+{
+	struct i2c_client *client = data->client;
+
+	i2c_smbus_write_word_data(data->client, cmd, val);
+}
+
+static int grove_set_state(struct grove_data *data, unsigned int which,
+		int state)
+{
+	static const u8 motor_addr[2] = { 0xa1, 0xa5 };
+
+	if (which > 1)
+		return -EINVAL;
+
+	switch (state) {
+
+		case GS_NONE:
+			/* nothing */
+			break;
+
+		case GS_SOLENOID_FORWARD:
+			grove_send_word(data, motor_addr[which], 0xff01);
+			break;
+
+		case GS_SOLENOID_BACKWARD:
+			grove_send_word(data, motor_addr[which], 0x0000);
+			break;
+
+		default:
+			/* unknown state */
+			return -EINVAL;
+	}
+
+	data->state[which] = state;
+
+	return 0;
+}
+
+static ssize_t grove_show_state(struct device *dev,
+		struct device_attribute *attr, char *buf, unsigned int which)
+{
+	struct grove_data *data = i2c_get_clientdata(to_i2c_client(dev));
+
+	if (which > 1)
+		return -EINVAL;
+
+	return sprintf(buf, "%u\n", data->state[which]);
+}
+
+static ssize_t grove_store_state(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count,
+		unsigned int which)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct grove_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	int ret;
+
+	if (which > 1)
+		return -EINVAL;
+
+	if (val < 0 || val > 2)
+		return -EINVAL;
+
+	mutex_lock(&data->lock);
+	ret = grove_set_state(data, which, val);
+	mutex_unlock(&data->lock);
+
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static ssize_t grove_show_stateA(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return grove_show_state(dev, attr, buf, 0);
+}
+
+static ssize_t grove_store_stateA(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	return grove_store_state(dev, attr, buf, count, 0);
+}
+
+static DEVICE_ATTR(stateA, S_IWUSR | S_IRUGO,
+		   grove_show_stateA, grove_store_stateA);
+
+static ssize_t grove_show_stateB(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return grove_show_state(dev, attr, buf, 1);
+}
+
+static ssize_t grove_store_stateB(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	return grove_store_state(dev, attr, buf, count, 1);
+}
+
+
+static DEVICE_ATTR(stateB, S_IWUSR | S_IRUGO,
+		   grove_show_stateB, grove_store_stateB);
+
+static struct attribute *grove_attributes[] = {
+	&dev_attr_stateA.attr,
+	&dev_attr_stateB.attr,
+	NULL
+};
+
+static const struct attribute_group grove_attr_group = {
+	.attrs = grove_attributes,
+};
+
+static int grove_init_client(struct i2c_client *client)
+{
+	struct grove_data *data = i2c_get_clientdata(client);
+
+	data->state[0] = GS_NONE;
+	data->state[1] = GS_NONE;
+
+	return 0;
+}
+
+static int grove_probe(struct i2c_client *client,
+				   const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct grove_data *data;
+	int err = 0;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE
+					    | I2C_FUNC_SMBUS_READ_BYTE_DATA))
+		return -EIO;
+
+	data = devm_kzalloc(dev, sizeof(struct grove_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->client = client;
+	i2c_set_clientdata(client, data);
+
+	mutex_init(&data->lock);
+
+	/* Initialize the TSL2550 chip */
+	err = grove_init_client(client);
+	if (err) {
+		dev_err(dev, "failed to init client\n");
+		goto exit_kfree;
+	}
+
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&client->dev.kobj, &grove_attr_group);
+	if (err) {
+		dev_err(dev, "failed to create sysfs group\n");
+		goto exit_kfree;
+	}
+
+	dev_info(dev, "Initialized OK\n");
+
+	return 0;
+
+exit_kfree:
+	devm_kfree(dev, data);
+	return err;
+}
+
+static int grove_remove(struct i2c_client *client)
+{
+	struct grove_data *data = i2c_get_clientdata(client);
+
+	sysfs_remove_group(&client->dev.kobj, &grove_attr_group);
+
+	devm_kfree(&client->dev, data);
+
+	return 0;
+}
+
+static const struct i2c_device_id grove_id[] = {
+	{ "grove", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, grove_id);
+
+static struct i2c_driver grove_driver = {
+	.driver = {
+		.name	= "grove-i2c",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= grove_probe,
+	.remove	= grove_remove,
+	.id_table = grove_id,
+};
+
+module_i2c_driver(grove_driver);
+
+MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
+MODULE_DESCRIPTION("Grove I2C Motor control driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 83269f1..d48b9e0 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -244,7 +244,7 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
 	if (version & 0x8000)
 		maj_ver |= 0x0008;
 
-	sprintf(bts_scr_name, "TIInit_%d.%d.%d.bts", chip, maj_ver, min_ver);
+	sprintf(bts_scr_name, "ti-connectivity/TIInit_%d.%d.%d.bts", chip, maj_ver, min_ver);
 
 	/* to be accessed later via sysfs entry */
 	kim_gdata->version.full = version;
@@ -287,7 +287,7 @@ static long download_firmware(struct kim_data_s *kim_gdata)
 	long len = 0;
 	unsigned char *ptr = NULL;
 	unsigned char *action_ptr = NULL;
-	unsigned char bts_scr_name[30] = { 0 };	/* 30 char long bts scr name? */
+	unsigned char bts_scr_name[50] = { 0 };	/* 50 char long bts scr name? */
 	int wr_room_space;
 	int cmd_size;
 	unsigned long timeout;
diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c
index 1e7bc0e..9255074 100644
--- a/drivers/misc/tsl2550.c
+++ b/drivers/misc/tsl2550.c
@@ -178,7 +178,7 @@ static int tsl2550_calculate_lux(u8 ch0, u8 ch1)
 		} else
 			lux = 0;
 	else
-		return -EAGAIN;
+		return 0;
 
 	/* LUX range check */
 	return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 009dabd..86d81ee 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -245,6 +245,7 @@ config MMC_OMAP
 	tristate "TI OMAP Multimedia Card Interface support"
 	depends on ARCH_OMAP
 	select TPS65010 if MACH_OMAP_H2
+	select RSTCTL
 	help
 	  This selects the TI OMAP Multimedia card Interface.
 	  If you have an OMAP board with a Multimedia Card slot,
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 2063677..d1efacc 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -35,6 +35,7 @@
 #include <linux/edma.h>
 #include <linux/mmc/mmc.h>
 
+#include <linux/platform_data/edma.h>
 #include <linux/platform_data/mmc-davinci.h>
 
 /*
@@ -144,18 +145,6 @@
 /* MMCSD Init clock in Hz in opendrain mode */
 #define MMCSD_INIT_CLOCK		200000
 
-/*
- * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units,
- * and we handle up to MAX_NR_SG segments.  MMC_BLOCK_BOUNCE kicks in only
- * for drivers with max_segs == 1, making the segments bigger (64KB)
- * than the page or two that's otherwise typical. nr_sg (passed from
- * platform data) == 16 gives at least the same throughput boost, using
- * EDMA transfer linkage instead of spending CPU time copying pages.
- */
-#define MAX_CCNT	((1 << 16) - 1)
-
-#define MAX_NR_SG	16
-
 static unsigned rw_threshold = 32;
 module_param(rw_threshold, uint, S_IRUGO);
 MODULE_PARM_DESC(rw_threshold,
@@ -216,8 +205,6 @@ struct mmc_davinci_host {
 	u8 version;
 	/* for ns in one cycle calculation */
 	unsigned ns_in_one_cycle;
-	/* Number of sg segments */
-	u8 nr_sg;
 #ifdef CONFIG_CPU_FREQ
 	struct notifier_block	freq_transition;
 #endif
@@ -421,16 +408,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
 	int ret = 0;
 
 	if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
-		struct dma_slave_config dma_tx_conf = {
-			.direction = DMA_MEM_TO_DEV,
-			.dst_addr = host->mem_res->start + DAVINCI_MMCDXR,
-			.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
-			.dst_maxburst =
-				rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES,
-		};
 		chan = host->dma_tx;
-		dmaengine_slave_config(host->dma_tx, &dma_tx_conf);
-
 		desc = dmaengine_prep_slave_sg(host->dma_tx,
 				data->sg,
 				host->sg_len,
@@ -443,16 +421,7 @@ static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host,
 			goto out;
 		}
 	} else {
-		struct dma_slave_config dma_rx_conf = {
-			.direction = DMA_DEV_TO_MEM,
-			.src_addr = host->mem_res->start + DAVINCI_MMCDRR,
-			.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
-			.src_maxburst =
-				rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES,
-		};
 		chan = host->dma_rx;
-		dmaengine_slave_config(host->dma_rx, &dma_rx_conf);
-
 		desc = dmaengine_prep_slave_sg(host->dma_rx,
 				data->sg,
 				host->sg_len,
@@ -1165,6 +1134,7 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
 	struct resource *r, *mem = NULL;
 	int ret = 0, irq = 0;
 	size_t mem_size;
+	struct dmaengine_chan_caps *dma_chan_caps;
 
 	/* REVISIT:  when we're fully converted, fail if pdata is NULL */
 
@@ -1214,12 +1184,6 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
 
 	init_mmcsd_host(host);
 
-	if (pdata->nr_sg)
-		host->nr_sg = pdata->nr_sg - 1;
-
-	if (host->nr_sg > MAX_NR_SG || !host->nr_sg)
-		host->nr_sg = MAX_NR_SG;
-
 	host->use_dma = use_dma;
 	host->mmc_irq = irq;
 	host->sdio_irq = platform_get_irq(pdev, 1);
@@ -1248,14 +1212,27 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
 		mmc->caps |= pdata->caps;
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
 
-	/* With no iommu coalescing pages, each phys_seg is a hw_seg.
-	 * Each hw_seg uses one EDMA parameter RAM slot, always one
-	 * channel and then usually some linked slots.
-	 */
-	mmc->max_segs		= MAX_NR_SG;
+	{
+		struct dma_slave_config dma_txrx_conf = {
+			.src_addr = host->mem_res->start + DAVINCI_MMCDRR,
+			.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+			.src_maxburst =
+				rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES,
+			.dst_addr = host->mem_res->start + DAVINCI_MMCDXR,
+			.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+			.dst_maxburst =
+				rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES,
+		};
+		dmaengine_slave_config(host->dma_tx, &dma_txrx_conf);
+		dmaengine_slave_config(host->dma_rx, &dma_txrx_conf);
+	}
 
-	/* EDMA limit per hw segment (one or two MBytes) */
-	mmc->max_seg_size	= MAX_CCNT * rw_threshold;
+	/* Just check one channel for the DMA SG limits */
+	dma_chan_caps = dma_get_channel_caps(host->dma_tx, DMA_MEM_TO_DEV);
+	if (dma_chan_caps) {
+		mmc->max_segs = dma_chan_caps->seg_nr;
+		mmc->max_seg_size = dma_chan_caps->seg_len;
+	}
 
 	/* MMC/SD controller limits for multiblock requests */
 	mmc->max_blk_size	= 4095;  /* BLEN is 12 bits */
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index bc58078..e2b97df 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -40,6 +40,11 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/platform_data/mmc-omap.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/err.h>
+#include <mach/hardware.h>
+#include <plat/cpu.h>
+#include <linux/rstctl.h>
 
 /* OMAP HSMMC Host Controller Registers */
 #define OMAP_HSMMC_SYSSTATUS	0x0014
@@ -183,6 +188,8 @@ struct omap_hsmmc_host {
 	struct omap_hsmmc_next	next_data;
 
 	struct	omap_mmc_platform_data	*pdata;
+
+	struct rstctl		*rstctl;
 };
 
 static int omap_hsmmc_card_detect(struct device *dev, int slot)
@@ -390,6 +397,7 @@ static inline int omap_hsmmc_have_reg(void)
 static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
 {
 	int ret;
+	unsigned long flags;
 
 	if (gpio_is_valid(pdata->slots[0].switch_pin)) {
 		if (pdata->slots[0].cover)
@@ -419,6 +427,24 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
 	} else
 		pdata->slots[0].gpio_wp = -EINVAL;
 
+	if (gpio_is_valid(pdata->slots[0].gpio_reset)) {
+		flags = pdata->slots[0].gpio_reset_active_low ?
+				GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
+		ret = gpio_request_one(pdata->slots[0].gpio_reset, flags,
+				"mmc_reset");
+		if (ret)
+			goto err_free_wp;
+
+		/* hold reset */
+		udelay(pdata->slots[0].gpio_reset_hold_us);
+
+		gpio_set_value(pdata->slots[0].gpio_reset,
+				!pdata->slots[0].gpio_reset_active_low);
+
+	} else
+		pdata->slots[0].gpio_reset = -EINVAL;
+
+
 	return 0;
 
 err_free_wp:
@@ -432,6 +458,8 @@ err_free_sp:
 
 static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
 {
+	if (gpio_is_valid(pdata->slots[0].gpio_reset))
+		gpio_free(pdata->slots[0].gpio_reset);
 	if (gpio_is_valid(pdata->slots[0].gpio_wp))
 		gpio_free(pdata->slots[0].gpio_wp);
 	if (gpio_is_valid(pdata->slots[0].switch_pin))
@@ -786,7 +814,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
 	 * ac, bc, adtc, bcr. Only commands ending an open ended transfer need
 	 * a val of 0x3, rest 0x0.
 	 */
-	if (cmd == host->mrq->stop)
+	if (host->mrq && cmd == host->mrq->stop)
 		cmdtype = 0x3;
 
 	cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22);
@@ -828,6 +856,8 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
 	int dma_ch;
 	unsigned long flags;
 
+	BUG_ON(mrq == NULL);
+
 	spin_lock_irqsave(&host->irq_lock, flags);
 	host->req_in_progress = 0;
 	dma_ch = host->dma_ch;
@@ -1717,6 +1747,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, max_freq;
+	enum of_gpio_flags reset_flags;
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
@@ -1729,6 +1760,14 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
 	pdata->nr_slots = 1;
 	pdata->slots[0].switch_pin = of_get_named_gpio(np, "cd-gpios", 0);
 	pdata->slots[0].gpio_wp = of_get_named_gpio(np, "wp-gpios", 0);
+	reset_flags = 0;
+	pdata->slots[0].gpio_reset = of_get_named_gpio_flags(np,
+			"reset-gpios", 0, &reset_flags);
+	pdata->slots[0].gpio_reset_active_low =
+		(reset_flags & OF_GPIO_ACTIVE_LOW) != 0;
+	pdata->slots[0].gpio_reset_hold_us = 100;	/* default */
+	of_property_read_u32(np, "reset-gpio-hold-us",
+			&pdata->slots[0].gpio_reset_hold_us);
 
 	if (of_find_property(np, "ti,non-removable", NULL)) {
 		pdata->slots[0].nonremovable = true;
@@ -1749,6 +1788,9 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
 	if (of_find_property(np, "ti,needs-special-hs-handling", NULL))
 		pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT;
 
+	if (of_find_property(np, "ti,vcc-aux-disable-is-sleep", NULL))
+		pdata->slots[0].vcc_aux_disable_is_sleep = 1;
+
 	return pdata;
 }
 #else
@@ -1769,7 +1811,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	const struct of_device_id *match;
 	dma_cap_mask_t mask;
 	unsigned tx_req, rx_req;
+	struct dmaengine_chan_caps *dma_chan_caps;
 	struct pinctrl *pinctrl;
+	struct rstctl *rctrl;
 
 	match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
 	if (match) {
@@ -1790,6 +1834,32 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
+	/* request reset control (bail if deffering) */
+	rctrl = rstctl_get(&pdev->dev, NULL);
+	if (IS_ERR(rctrl)) {
+		ret = PTR_ERR(rctrl);
+		if (ret == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		if (ret != -ENODEV && ret != -ENOENT) {
+			dev_err(&pdev->dev, "Unrecoverable rstctl error\n");
+			return PTR_ERR(rctrl);
+		}
+		dev_warn(&pdev->dev, "Failed to get rstctl; not using any\n");
+		rctrl = NULL;
+	} else {
+		dev_info(&pdev->dev, "Got rstctl (%s:#%d name %s) label:%s\n",
+				rctrl->rdev->rdesc->name,
+				rctrl->line - rctrl->rdev->rdesc->lines,
+				rctrl->line->name, rctrl->label);
+
+		rstctl_deassert(rctrl);
+	}
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev, "unable to select pin group\n");
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(pdev, 0);
 	if (res == NULL || irq < 0)
@@ -1821,6 +1891,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	host->base	= ioremap(host->mapbase, SZ_4K);
 	host->power_mode = MMC_POWER_OFF;
 	host->next_data.cookie = 1;
+	host->rstctl	= rctrl;
 
 	platform_set_drvdata(pdev, host);
 
@@ -1877,6 +1948,16 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	 * as we want. */
 	mmc->max_segs = 1024;
 
+	/* Eventually we should get our max_segs limitation for EDMA by
+	 * querying the dmaengine API */
+	if (pdev->dev.of_node) {
+		struct device_node *parent = of_node_get(pdev->dev.of_node->parent);
+		struct device_node *node;
+		node = of_find_node_by_name(parent, "edma");
+		if (node)
+			mmc->max_segs = 16;
+	}
+
 	mmc->max_blk_size = 512;       /* Block Length at max can be 1024 */
 	mmc->max_blk_count = 0xFFFF;    /* No. of Blocks is 16 bits */
 	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
@@ -1915,20 +1996,31 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_SLAVE, mask);
 
-	host->rx_chan = dma_request_channel(mask, omap_dma_filter_fn, &rx_req);
+	host->rx_chan =
+		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+						 &rx_req, &pdev->dev, "rx");
+
 	if (!host->rx_chan) {
 		dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", rx_req);
 		ret = -ENXIO;
 		goto err_irq;
 	}
 
-	host->tx_chan = dma_request_channel(mask, omap_dma_filter_fn, &tx_req);
+	host->tx_chan =
+		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+						 &tx_req, &pdev->dev, "tx");
+
 	if (!host->tx_chan) {
 		dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", tx_req);
 		ret = -ENXIO;
 		goto err_irq;
 	}
 
+	/* Some DMA Engines only handle a limited number of SG segments */
+	dma_chan_caps = dma_get_channel_caps(host->rx_chan, DMA_DEV_TO_MEM);
+	if (dma_chan_caps && dma_chan_caps->seg_nr)
+		mmc->max_segs = dma_chan_caps->seg_nr;
+
 	/* Request IRQ for MMC operations */
 	ret = request_irq(host->irq, omap_hsmmc_irq, 0,
 			mmc_hostname(mmc), host);
@@ -2065,6 +2157,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
 
 	omap_hsmmc_gpio_free(host->pdata);
 	iounmap(host->base);
+	rstctl_put(host->rstctl);
 	mmc_free_host(host->mmc);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 0002d5e..1d333497c 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1332,6 +1332,7 @@ static int omap_nand_probe(struct platform_device *pdev)
 	dma_cap_mask_t mask;
 	unsigned sig;
 	struct resource			*res;
+	struct mtd_part_parser_data	ppdata = {};
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -1557,7 +1558,8 @@ static int omap_nand_probe(struct platform_device *pdev)
 		goto out_release_mem_region;
 	}
 
-	mtd_device_parse_register(&info->mtd, NULL, NULL, pdata->parts,
+	ppdata.of_node = pdata->of_node;
+	mtd_device_parse_register(&info->mtd, NULL, &ppdata, pdata->parts,
 				  pdata->nr_parts);
 
 	platform_set_drvdata(pdev, &info->mtd);
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 065f3fe..eec2aed 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -637,6 +637,7 @@ static int omap2_onenand_probe(struct platform_device *pdev)
 	struct onenand_chip *this;
 	int r;
 	struct resource *res;
+	struct mtd_part_parser_data ppdata = {};
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -767,7 +768,8 @@ static int omap2_onenand_probe(struct platform_device *pdev)
 	if ((r = onenand_scan(&c->mtd, 1)) < 0)
 		goto err_release_regulator;
 
-	r = mtd_device_parse_register(&c->mtd, NULL, NULL,
+	ppdata.of_node = pdata->of_node;
+	r = mtd_device_parse_register(&c->mtd, NULL, &ppdata,
 				      pdata ? pdata->parts : NULL,
 				      pdata ? pdata->nr_parts : 0);
 	if (r)
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
index 42b6d69..a7f2418 100644
--- a/drivers/net/can/mcp251x.c
+++ b/drivers/net/can/mcp251x.c
@@ -1,6 +1,9 @@
 /*
  * CAN bus driver for Microchip 251x CAN Controller with SPI Interface
  *
+ * Copyright (C) 2013 Tower Technologies
+ * Device Tree by Alessandro Zummo <a.zummo@towertech.it>
+ *
  * MCP2510 support and bug fixes by Christian Pellegrin
  * <chripell@evolware.org>
  *
@@ -72,6 +75,10 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
 #include <linux/uaccess.h>
@@ -98,8 +105,9 @@
 #  define CANCTRL_REQOP_LOOPBACK    0x40
 #  define CANCTRL_REQOP_SLEEP	    0x20
 #  define CANCTRL_REQOP_NORMAL	    0x00
-#  define CANCTRL_OSM		    0x08
 #  define CANCTRL_ABAT		    0x10
+#  define CANCTRL_OSM		    0x08
+#  define CANCTRL_CLKEN		    0x04
 #define TEC	      0x1c
 #define REC	      0x1d
 #define CNF1	      0x2a
@@ -237,9 +245,13 @@ enum mcp251x_model {
 };
 
 struct mcp251x_priv {
+
 	struct can_priv	   can;
 	struct net_device *net;
 	struct spi_device *spi;
+
+	struct mcp251x_platform_data *pdata;
+
 	enum mcp251x_model model;
 
 	struct mutex mcp_lock; /* SPI device lock */
@@ -292,7 +304,7 @@ static void mcp251x_clean(struct net_device *net)
 /*
  * Note about handling of error return of mcp251x_spi_trans: accessing
  * registers via SPI is not really different conceptually than using
- * normal I/O assembler instructions, although it's much more
+ * normal I/O assembly instructions, although it's much more
  * complicated from a practical POV. So it's not advisable to always
  * check the return value of this function. Imagine that every
  * read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0)
@@ -499,7 +511,10 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
 
 static void mcp251x_hw_sleep(struct spi_device *spi)
 {
-	mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP);
+	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
+
+	if (!priv->pdata->stay_awake)
+		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP);
 }
 
 static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb,
@@ -556,13 +571,18 @@ static int mcp251x_set_normal_mode(struct spi_device *spi)
 
 	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
 		/* Put device into loopback mode */
-		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK);
+		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK | (priv->pdata->enable_clkout ? CANCTRL_CLKEN : 0));
+
 	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
 		/* Put device into listen-only mode */
-		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY);
+		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY | (priv->pdata->enable_clkout ? CANCTRL_CLKEN : 0));
+
 	} else {
 		/* Put device into normal mode */
-		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL);
+		mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL | (priv->pdata->enable_clkout ? CANCTRL_CLKEN : 0));
+
+		netdev_info(priv->net, "CANCTRL: 0x%02x\n",
+		mcp251x_read_reg(spi, CANCTRL));
 
 		/* Wait for the device to enter normal mode */
 		timeout = jiffies + HZ;
@@ -594,11 +614,15 @@ static int mcp251x_do_set_bittiming(struct net_device *net)
 			  (bt->prop_seg - 1));
 	mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK,
 			   (bt->phase_seg2 - 1));
-	dev_info(&spi->dev, "CNF: 0x%02x 0x%02x 0x%02x\n",
+
+	netdev_info(net, "CNF: 0x%02x 0x%02x 0x%02x\n",
 		 mcp251x_read_reg(spi, CNF1),
 		 mcp251x_read_reg(spi, CNF2),
 		 mcp251x_read_reg(spi, CNF3));
 
+	netdev_info(net, "CANCTRL: 0x%02x\n",
+		 mcp251x_read_reg(spi, CANCTRL));
+
 	return 0;
 }
 
@@ -609,6 +633,7 @@ static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv,
 
 	mcp251x_write_reg(spi, RXBCTRL(0),
 			  RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1);
+
 	mcp251x_write_reg(spi, RXBCTRL(1),
 			  RXBCTRL_RXM0 | RXBCTRL_RXM1);
 	return 0;
@@ -667,7 +692,7 @@ static void mcp251x_open_clean(struct net_device *net)
 {
 	struct mcp251x_priv *priv = netdev_priv(net);
 	struct spi_device *spi = priv->spi;
-	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
+	struct mcp251x_platform_data *pdata = priv->pdata;
 
 	free_irq(spi->irq, priv);
 	mcp251x_hw_sleep(spi);
@@ -680,7 +705,7 @@ static int mcp251x_stop(struct net_device *net)
 {
 	struct mcp251x_priv *priv = netdev_priv(net);
 	struct spi_device *spi = priv->spi;
-	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
+	struct mcp251x_platform_data *pdata = priv->pdata;
 
 	close_candev(net);
 
@@ -736,7 +761,9 @@ static void mcp251x_tx_work_handler(struct work_struct *ws)
 	mutex_lock(&priv->mcp_lock);
 	if (priv->tx_skb) {
 		if (priv->can.state == CAN_STATE_BUS_OFF) {
+
 			mcp251x_clean(net);
+
 		} else {
 			frame = (struct can_frame *)priv->tx_skb->data;
 
@@ -835,21 +862,37 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
 
 		/* Update can state */
 		if (eflag & EFLG_TXBO) {
+
+			netdev_err(net, "err: bus off\n");
+
 			new_state = CAN_STATE_BUS_OFF;
 			can_id |= CAN_ERR_BUSOFF;
 		} else if (eflag & EFLG_TXEP) {
+
+			netdev_err(net, "err: txep\n");
+
 			new_state = CAN_STATE_ERROR_PASSIVE;
 			can_id |= CAN_ERR_CRTL;
 			data1 |= CAN_ERR_CRTL_TX_PASSIVE;
+
 		} else if (eflag & EFLG_RXEP) {
+
+			netdev_err(net, "err: rxep\n");
+
 			new_state = CAN_STATE_ERROR_PASSIVE;
 			can_id |= CAN_ERR_CRTL;
 			data1 |= CAN_ERR_CRTL_RX_PASSIVE;
 		} else if (eflag & EFLG_TXWAR) {
+
+			netdev_err(net, "err: txwar\n");
+
 			new_state = CAN_STATE_ERROR_WARNING;
 			can_id |= CAN_ERR_CRTL;
 			data1 |= CAN_ERR_CRTL_TX_WARNING;
 		} else if (eflag & EFLG_RXWAR) {
+
+			netdev_err(net, "err: rxwar\n");
+
 			new_state = CAN_STATE_ERROR_WARNING;
 			can_id |= CAN_ERR_CRTL;
 			data1 |= CAN_ERR_CRTL_RX_WARNING;
@@ -921,13 +964,13 @@ static int mcp251x_open(struct net_device *net)
 {
 	struct mcp251x_priv *priv = netdev_priv(net);
 	struct spi_device *spi = priv->spi;
-	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
-	unsigned long flags;
+	struct mcp251x_platform_data *pdata = priv->pdata;
+	unsigned long flags = 0;
 	int ret;
 
 	ret = open_candev(net);
 	if (ret) {
-		dev_err(&spi->dev, "unable to set initial baudrate!\n");
+		netdev_err(net, "failed to open can device\n");
 		return ret;
 	}
 
@@ -939,16 +982,15 @@ static int mcp251x_open(struct net_device *net)
 	priv->tx_skb = NULL;
 	priv->tx_len = 0;
 
-	flags = IRQF_ONESHOT;
 	if (pdata->irq_flags)
 		flags |= pdata->irq_flags;
 	else
 		flags |= IRQF_TRIGGER_FALLING;
 
 	ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist,
-				   flags, DEVICE_NAME, priv);
+				   IRQF_ONESHOT | flags, dev_name(&net->dev), priv);
 	if (ret) {
-		dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
+		netdev_err(net, "failed to acquire irq %d\n", spi->irq);
 		if (pdata->transceiver_enable)
 			pdata->transceiver_enable(0);
 		close_candev(net);
@@ -987,21 +1029,79 @@ static const struct net_device_ops mcp251x_netdev_ops = {
 	.ndo_start_xmit = mcp251x_hard_start_xmit,
 };
 
+static struct mcp251x_platform_data *
+mcp251x_platform_data_dt_get(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct mcp251x_platform_data *pd;
+
+	u32 tmp;
+	int err, gpio;
+
+	dev_dbg(dev, "reading device tree\n");
+
+	if (!np) {
+		dev_err(dev, "no device tree node defined\n");
+		return NULL;
+	}
+
+	pd = devm_kzalloc(dev, sizeof(struct mcp251x_platform_data), GFP_KERNEL);
+	if (!pd) {
+		dev_err(dev, "cannot allocate platform data memory\n");
+		return NULL;
+	}
+
+	of_property_read_u32(np, "mcp251x,oscillator-frequency", &tmp);
+	pd->oscillator_frequency = tmp;
+
+	pd->stay_awake = of_property_read_bool(np, "mcp251x,stay-awake");
+	pd->enable_clkout = of_property_read_bool(np, "mcp251x,enable-clkout");
+
+	gpio = of_get_named_gpio(np, "mcp251x,irq-gpios", 0);
+	if (gpio_is_valid(gpio)) {
+		err = devm_gpio_request_one(dev, gpio, GPIOF_DIR_IN, "mcp251x-irq");
+		if (err) {
+			dev_err(dev, "cannot request gpio %d\n", gpio);
+			return NULL;
+		}
+	} else {
+			dev_warn(dev, "mcp251x,irq-gpios missing or invalid\n");
+	}
+
+	return pd;
+}
+
 static int mcp251x_can_probe(struct spi_device *spi)
 {
 	struct net_device *net;
 	struct mcp251x_priv *priv;
 	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
+	struct pinctrl *pinctrl;
 	int ret = -ENODEV;
 
-	if (!pdata)
+	dev_dbg(&spi->dev, "probing\n");
+
+	if (!pdata && IS_ENABLED(CONFIG_OF))
+		pdata = mcp251x_platform_data_dt_get(&spi->dev);
+
+	if (!pdata) {
 		/* Platform data is required for osc freq */
+		dev_err(&spi->dev, "missing platform data\n");
 		goto error_out;
+	}
+
+	dev_info(&spi->dev, "mode %d, irq %d, awake %d, clkout %d, oscillator freq %ld\n",
+			spi->mode, spi->irq, pdata->stay_awake, pdata->enable_clkout, pdata->oscillator_frequency);
+
+	pinctrl = devm_pinctrl_get_select_default(&spi->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&spi->dev, "pinctrl pins are not configured from the driver");
 
 	/* Allocate can/net device */
 	net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX);
 	if (!net) {
 		ret = -ENOMEM;
+		dev_err(&spi->dev, "alloc_candev failed\n");
 		goto error_alloc;
 	}
 
@@ -1009,16 +1109,22 @@ static int mcp251x_can_probe(struct spi_device *spi)
 	net->flags |= IFF_ECHO;
 
 	priv = netdev_priv(net);
-	priv->can.bittiming_const = &mcp251x_bittiming_const;
+
+	priv->net = net;
+	priv->spi = spi;
+	priv->pdata = pdata;
+
+	priv->model = spi_get_device_id(spi)->driver_data;
+
 	priv->can.do_set_mode = mcp251x_do_set_mode;
 	priv->can.clock.freq = pdata->oscillator_frequency / 2;
+	priv->can.bittiming_const = &mcp251x_bittiming_const;
+
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
 		CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
-	priv->model = spi_get_device_id(spi)->driver_data;
-	priv->net = net;
+
 	dev_set_drvdata(&spi->dev, priv);
 
-	priv->spi = spi;
 	mutex_init(&priv->mcp_lock);
 
 	/* If requested, allocate DMA buffers */
@@ -1068,13 +1174,13 @@ static int mcp251x_can_probe(struct spi_device *spi)
 	SET_NETDEV_DEV(net, &spi->dev);
 
 	/* Configure the SPI bus */
-	spi->mode = SPI_MODE_0;
+	//spi->mode = SPI_MODE_0;
 	spi->bits_per_word = 8;
 	spi_setup(spi);
 
 	/* Here is OK to not lock the MCP, no one knows about it yet */
 	if (!mcp251x_hw_probe(spi)) {
-		dev_info(&spi->dev, "Probe failed\n");
+		dev_info(&spi->dev, "hw probe failed\n");
 		goto error_probe;
 	}
 	mcp251x_hw_sleep(spi);
@@ -1084,7 +1190,7 @@ static int mcp251x_can_probe(struct spi_device *spi)
 
 	ret = register_candev(net);
 	if (!ret) {
-		dev_info(&spi->dev, "probed\n");
+		netdev_info(priv->net, "probed\n");
 		return ret;
 	}
 error_probe:
@@ -1108,8 +1214,8 @@ error_out:
 
 static int mcp251x_can_remove(struct spi_device *spi)
 {
-	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
 	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
+	struct mcp251x_platform_data *pdata = priv->pdata;
 	struct net_device *net = priv->net;
 
 	unregister_candev(net);
@@ -1132,8 +1238,8 @@ static int mcp251x_can_remove(struct spi_device *spi)
 #ifdef CONFIG_PM
 static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state)
 {
-	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
 	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
+	struct mcp251x_platform_data *pdata = priv->pdata;
 	struct net_device *net = priv->net;
 
 	priv->force_quit = 1;
@@ -1163,8 +1269,8 @@ static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state)
 
 static int mcp251x_can_resume(struct spi_device *spi)
 {
-	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
 	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
+	struct mcp251x_platform_data *pdata = priv->pdata;
 
 	if (priv->after_suspend & AFTER_SUSPEND_POWER) {
 		pdata->power_enable(1);
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index e112877..8907fde 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -1107,6 +1107,7 @@ static void smsc911x_tx_update_txcounters(struct net_device *dev)
 {
 	struct smsc911x_data *pdata = netdev_priv(dev);
 	unsigned int tx_stat;
+	unsigned int bytes_compl = 0, pkts_compl = 0;
 
 	while ((tx_stat = smsc911x_tx_get_txstatus(pdata)) != 0) {
 		if (unlikely(tx_stat & 0x80000000)) {
@@ -1124,6 +1125,8 @@ static void smsc911x_tx_update_txcounters(struct net_device *dev)
 			} else {
 				dev->stats.tx_packets++;
 				dev->stats.tx_bytes += (tx_stat >> 16);
+				pkts_compl++;
+				bytes_compl += (tx_stat >> 16);
 			}
 			if (unlikely(tx_stat & TX_STS_EXCESS_COL_)) {
 				dev->stats.collisions += 16;
@@ -1140,6 +1143,7 @@ static void smsc911x_tx_update_txcounters(struct net_device *dev)
 			}
 		}
 	}
+	netdev_completed_queue(dev, pkts_compl, bytes_compl);
 }
 
 /* Increments the Rx error counters */
@@ -1602,6 +1606,7 @@ static int smsc911x_stop(struct net_device *dev)
 	/* At this point all Rx and Tx activity is stopped */
 	dev->stats.rx_dropped += smsc911x_reg_read(pdata, RX_DROP);
 	smsc911x_tx_update_txcounters(dev);
+	netdev_reset_queue(dev);
 
 	/* Bring the PHY down */
 	if (pdata->phy_dev)
@@ -1645,6 +1650,7 @@ static int smsc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	wrsz >>= 2;
 
 	pdata->ops->tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
+	netdev_sent_queue(dev, skb->len);
 	freespace -= (skb->len + 32);
 	skb_tx_timestamp(skb);
 	dev_kfree_skb(skb);
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 3b1be52..21ba53e 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -148,10 +148,37 @@ struct cpsw_wr_regs {
 	u32	soft_reset;
 	u32	control;
 	u32	int_control;
-	u32	rx_thresh_en;
-	u32	rx_en;
-	u32	tx_en;
-	u32	misc_en;
+	u32	c0_rx_thresh_en;
+	u32	c0_rx_en;
+	u32	c0_tx_en;
+	u32	c0_misc_en;
+	u32	c1_rx_thresh_en;
+	u32	c1_rx_en;
+	u32	c1_tx_en;
+	u32	c1_misc_en;
+	u32	c2_rx_thresh_en;
+	u32	c2_rx_en;
+	u32	c2_tx_en;
+	u32	c2_misc_en;
+	u32	c0_rx_thresh_stat;
+	u32	c0_rx_stat;
+	u32	c0_tx_stat;
+	u32	c0_misc_stat;
+	u32	c1_rx_thresh_stat;
+	u32	c1_rx_stat;
+	u32	c1_tx_stat;
+	u32	c1_misc_stat;
+	u32	c2_rx_thresh_stat;
+	u32	c2_rx_stat;
+	u32	c2_tx_stat;
+	u32	c2_misc_stat;
+	u32	c0_rx_imax;
+	u32	c0_tx_imax;
+	u32	c1_rx_imax;
+	u32	c1_tx_imax;
+	u32	c2_rx_imax;
+	u32	c2_tx_imax;
+	u32	rgmii_ctl;
 };
 
 struct cpsw_ss_regs {
@@ -352,8 +379,8 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
 
 static void cpsw_intr_enable(struct cpsw_priv *priv)
 {
-	__raw_writel(0xFF, &priv->wr_regs->tx_en);
-	__raw_writel(0xFF, &priv->wr_regs->rx_en);
+	__raw_writel(0xFF, &priv->wr_regs->c0_tx_en);
+	__raw_writel(0xFF, &priv->wr_regs->c0_rx_en);
 
 	cpdma_ctlr_int_ctrl(priv->dma, true);
 	return;
@@ -361,8 +388,8 @@ static void cpsw_intr_enable(struct cpsw_priv *priv)
 
 static void cpsw_intr_disable(struct cpsw_priv *priv)
 {
-	__raw_writel(0, &priv->wr_regs->tx_en);
-	__raw_writel(0, &priv->wr_regs->rx_en);
+	__raw_writel(0, &priv->wr_regs->c0_tx_en);
+	__raw_writel(0, &priv->wr_regs->c0_rx_en);
 
 	cpdma_ctlr_int_ctrl(priv->dma, false);
 	return;
@@ -399,7 +426,10 @@ void cpsw_rx_handler(void *token, int len, int status)
 		skb_put(skb, len);
 		cpts_rx_timestamp(&priv->cpts, skb);
 		skb->protocol = eth_type_trans(skb, ndev);
-		netif_receive_skb(skb);
+		if (priv->data.disable_napi)
+			netif_rx(skb);
+		else
+			netif_receive_skb(skb);
 		priv->stats.rx_bytes += len;
 		priv->stats.rx_packets++;
 		skb = NULL;
@@ -431,6 +461,7 @@ static irqreturn_t cpsw_interrupt(int irq, void *dev_id)
 		cpsw_disable_irq(priv);
 		napi_schedule(&priv->napi);
 	}
+
 	return IRQ_HANDLED;
 }
 
@@ -445,23 +476,104 @@ static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
 static int cpsw_poll(struct napi_struct *napi, int budget)
 {
 	struct cpsw_priv	*priv = napi_to_priv(napi);
-	int			num_tx, num_rx;
+	int			num_tx, num_rx, num_total_tx, num_total_rx;
+	int			budget_left;
+
+	budget_left = budget;
 
-	num_tx = cpdma_chan_process(priv->txch, 128);
-	num_rx = cpdma_chan_process(priv->rxch, budget);
+	/* read status and throw away */
+	(void)__raw_readl(&priv->wr_regs->c0_tx_stat);
+
+	/* handle all transmits */
+	num_total_tx = 0;
+	while (budget_left > 0 &&
+		(num_tx = cpdma_chan_process(priv->txch, 128)) > 0) {
+		budget_left -= num_tx;
+		num_total_tx += num_tx;
+	}
 
-	if (num_rx || num_tx)
-		cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n",
-			 num_rx, num_tx);
+	if (num_total_tx > 0 && budget_left > 0)
+		cpdma_ctlr_eoi(priv->dma, 0x02);
+
+	/* read status and throw away */
+	(void)__raw_readl(&priv->wr_regs->c0_rx_stat);
+
+	/* handle all receives */
+	num_total_rx = 0;
+	while (budget_left > 0 &&
+		(num_rx = cpdma_chan_process(priv->rxch, budget_left)) > 0) {
+		budget_left -= num_rx;
+		num_total_rx += num_rx;
+	}
 
-	if (num_rx < budget) {
+	if (num_total_rx > 0 && budget_left > 0)
+		cpdma_ctlr_eoi(priv->dma, 0x01);
+
+	if ((num_total_rx + num_total_tx) < budget) {
 		napi_complete(napi);
 		cpsw_intr_enable(priv);
-		cpdma_ctlr_eoi(priv->dma);
 		cpsw_enable_irq(priv);
 	}
 
-	return num_rx;
+	return num_total_rx + num_total_rx;
+}
+
+static irqreturn_t cpsw_rx_thresh_pend_irq(int irq, void *dev_id)
+{
+	struct cpsw_priv *priv = dev_id;
+
+	(void)priv;
+
+	/* not handling this interrupt yet */
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t cpsw_rx_pend_irq(int irq, void *dev_id)
+{
+	struct cpsw_priv *priv = dev_id;
+	int num_rx, total_rx;
+	u32 rx_stat;
+
+	rx_stat = __raw_readl(&priv->wr_regs->c0_rx_stat) & 0xff;
+	if (rx_stat == 0)
+		return IRQ_NONE;
+
+	total_rx = 0;
+	while ((num_rx = cpdma_chan_process(priv->rxch,
+					priv->data.rx_descs)) > 0)
+		total_rx += num_rx;
+
+	cpdma_ctlr_eoi(priv->dma, 0x01);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t cpsw_tx_pend_irq(int irq, void *dev_id)
+{
+	struct cpsw_priv *priv = dev_id;
+	int num_tx, total_tx;
+	u32 tx_stat;
+
+	tx_stat = __raw_readl(&priv->wr_regs->c0_tx_stat) & 0xff;
+	if (tx_stat == 0)
+		return IRQ_NONE;
+
+	total_tx = 0;
+	while ((num_tx = cpdma_chan_process(priv->txch, 128)) > 0)
+		total_tx += num_tx;
+
+	cpdma_ctlr_eoi(priv->dma, 0x02);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t cpsw_misc_pend_irq(int irq, void *dev_id)
+{
+	struct cpsw_priv *priv = dev_id;
+
+	(void)priv;
+	/* not handling this interrupt yet */
+	return IRQ_HANDLED;
 }
 
 static inline void soft_reset(const char *module, void __iomem *reg)
@@ -678,8 +790,10 @@ static int cpsw_ndo_open(struct net_device *ndev)
 
 	cpdma_ctlr_start(priv->dma);
 	cpsw_intr_enable(priv);
-	napi_enable(&priv->napi);
-	cpdma_ctlr_eoi(priv->dma);
+	if (!priv->data.disable_napi)
+		napi_enable(&priv->napi);
+	cpdma_ctlr_eoi(priv->dma, 0x01);
+	cpdma_ctlr_eoi(priv->dma, 0x02);
 
 	return 0;
 }
@@ -698,8 +812,10 @@ 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_disable_irq(priv);
 	netif_stop_queue(priv->ndev);
-	napi_disable(&priv->napi);
+	if (!priv->data.disable_napi)
+		napi_disable(&priv->napi);
 	netif_carrier_off(priv->ndev);
 	cpsw_intr_disable(priv);
 	cpdma_ctlr_int_ctrl(priv->dma, false);
@@ -901,7 +1017,8 @@ static void cpsw_ndo_tx_timeout(struct net_device *ndev)
 	cpdma_chan_start(priv->txch);
 	cpdma_ctlr_int_ctrl(priv->dma, true);
 	cpsw_intr_enable(priv);
-	cpdma_ctlr_eoi(priv->dma);
+	cpdma_ctlr_eoi(priv->dma, 0x01);
+	cpdma_ctlr_eoi(priv->dma, 0x02);
 }
 
 static struct net_device_stats *cpsw_ndo_get_stats(struct net_device *ndev)
@@ -917,14 +1034,21 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
 
 	cpsw_intr_disable(priv);
 	cpdma_ctlr_int_ctrl(priv->dma, false);
-	cpsw_interrupt(ndev->irq, priv);
+	if (!priv->data.disable_napi)
+		cpsw_interrupt(ndev->irq, priv);
+	else {
+		/* bah! */
+		cpsw_rx_pend_irq(ndev->irq, priv);
+		cpsw_tx_pend_irq(ndev->irq, priv);
+	}
 	cpdma_ctlr_int_ctrl(priv->dma, true);
 	cpsw_intr_enable(priv);
-	cpdma_ctlr_eoi(priv->dma);
+	cpdma_ctlr_eoi(priv->dma, 0x01);
+	cpdma_ctlr_eoi(priv->dma, 0x02);
 }
 #endif
 
-static const struct net_device_ops cpsw_netdev_ops = {
+static struct net_device_ops cpsw_netdev_ops = {
 	.ndo_open		= cpsw_ndo_open,
 	.ndo_stop		= cpsw_ndo_stop,
 	.ndo_start_xmit		= cpsw_ndo_start_xmit,
@@ -1079,6 +1203,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
 	}
 	data->bd_ram_size = prop;
 
+	if (of_property_read_bool(node, "disable-napi"))
+		data->disable_napi = 1;
+
 	if (of_property_read_u32(node, "rx_descs", &prop)) {
 		pr_err("Missing rx_descs property in the DT.\n");
 		ret = -EINVAL;
@@ -1136,6 +1263,22 @@ error_ret:
 	return ret;
 }
 
+static irq_handler_t cpsw_get_irq_handler(struct cpsw_priv *priv, int irq_idx)
+{
+	static const irq_handler_t non_napi_irq_tab[4] = {
+		cpsw_rx_thresh_pend_irq, cpsw_rx_pend_irq,
+		cpsw_tx_pend_irq, cpsw_misc_pend_irq
+	};
+
+	if ((unsigned int)irq_idx >= 4)
+		return NULL;
+
+	if (!priv->data.disable_napi)
+		return cpsw_interrupt;
+
+	return non_napi_irq_tab[irq_idx];
+}
+
 static int cpsw_probe(struct platform_device *pdev)
 {
 	struct cpsw_platform_data	*data = pdev->dev.platform_data;
@@ -1146,7 +1289,8 @@ static int cpsw_probe(struct platform_device *pdev)
 	void __iomem			*ss_regs, *wr_regs;
 	struct resource			*res;
 	u32 slave_offset, sliver_offset, slave_size;
-	int ret = 0, i, k = 0;
+	irq_handler_t			irqh;
+	int ret = 0, i, j, k = 0;
 
 	ndev = alloc_etherdev(sizeof(struct cpsw_priv));
 	if (!ndev) {
@@ -1333,24 +1477,36 @@ static int cpsw_probe(struct platform_device *pdev)
 		goto clean_ale_ret;
 	}
 
-	while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
-		for (i = res->start; i <= res->end; i++) {
-			if (request_irq(i, cpsw_interrupt, IRQF_DISABLED,
+	dev_info(&pdev->dev, "NAPI %s\n", priv->data.disable_napi ?
+			"disabled" : "enabled");
+
+	/* get interrupts */
+	j = k = 0;
+	while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, j++))) {
+		for (i = res->start; k < 4 && i <= res->end; i++) {
+			irqh = cpsw_get_irq_handler(priv, k);
+			if (irqh == NULL) {
+				dev_err(&pdev->dev, "Unable to get handler "
+						"for #%d (%d)\n", k, i);
+				goto clean_ale_ret;
+			}
+			if (request_irq(i, irqh, IRQF_DISABLED,
 					dev_name(&pdev->dev), priv)) {
 				dev_err(priv->dev, "error attaching irq\n");
 				goto clean_ale_ret;
 			}
-			priv->irqs_table[k] = i;
-			priv->num_irqs = k;
+			priv->irqs_table[k++] = i;
 		}
-		k++;
 	}
+	priv->num_irqs = k;
 
 	ndev->flags |= IFF_ALLMULTI;	/* see cpsw_ndo_change_rx_flags() */
 
 	ndev->netdev_ops = &cpsw_netdev_ops;
 	SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
-	netif_napi_add(ndev, &priv->napi, cpsw_poll, CPSW_POLL_WEIGHT);
+
+	if (!priv->data.disable_napi)
+		netif_napi_add(ndev, &priv->napi, cpsw_poll, CPSW_POLL_WEIGHT);
 
 	/* register the network device */
 	SET_NETDEV_DEV(ndev, &pdev->dev);
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index 4995673..6effab2 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -474,9 +474,9 @@ int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
 	return 0;
 }
 
-void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr)
+void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr, u32 value)
 {
-	dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0);
+	dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, value);
 }
 
 struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.h b/drivers/net/ethernet/ti/davinci_cpdma.h
index afa19a0..b7c097d 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.h
+++ b/drivers/net/ethernet/ti/davinci_cpdma.h
@@ -86,7 +86,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
 int cpdma_chan_process(struct cpdma_chan *chan, int quota);
 
 int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
-void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr);
+void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr, u32 value);
 int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable);
 
 enum cpdma_control {
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
index 3f2c7aa..6481faf 100644
--- a/drivers/net/ieee802154/mrf24j40.c
+++ b/drivers/net/ieee802154/mrf24j40.c
@@ -22,6 +22,7 @@
 #include <linux/spi/spi.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
 #include <net/wpan-phy.h>
 #include <net/mac802154.h>
 
@@ -91,9 +92,8 @@ struct mrf24j40 {
 #define MRF24J40_READLONG(reg) (1 << 15 | (reg) << 5)
 #define MRF24J40_WRITELONG(reg) (1 << 15 | (reg) << 5 | 1 << 4)
 
-/* Maximum speed to run the device at. TODO: Get the real max value from
- * someone at Microchip since it isn't in the datasheet. */
-#define MAX_SPI_SPEED_HZ 1000000
+/* The datasheet indicates the theoretical maximum for SCK to be 10MHz */
+#define MAX_SPI_SPEED_HZ 10000000
 
 #define printdev(X) (&X->spi->dev)
 
@@ -362,6 +362,7 @@ static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
 		goto err;
 	if (ret == 0) {
 		ret = -ETIMEDOUT;
+		dev_warn(printdev(devrec), "Timeout waiting for TX interrupt\n");
 		goto err;
 	}
 
@@ -477,7 +478,7 @@ static int mrf24j40_filter(struct ieee802154_dev *dev,
 		int i;
 		for (i = 0; i < 8; i++)
 			write_short_reg(devrec, REG_EADR0+i,
-					filt->ieee_addr[i]);
+					filt->ieee_addr[7-i]);
 
 #ifdef DEBUG
 		printk(KERN_DEBUG "Set long addr to: ");
@@ -623,6 +624,7 @@ static int mrf24j40_probe(struct spi_device *spi)
 	int ret = -ENOMEM;
 	u8 val;
 	struct mrf24j40 *devrec;
+	struct pinctrl *pinctrl;
 
 	printk(KERN_INFO "mrf24j40: probe(). IRQ: %d\n", spi->irq);
 
@@ -633,6 +635,11 @@ static int mrf24j40_probe(struct spi_device *spi)
 	if (!devrec->buf)
 		goto err_buf;
 
+	pinctrl = devm_pinctrl_get_select_default(&spi->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&spi->dev,
+			"pinctrl pins are not configured from the driver");
+
 	spi->mode = SPI_MODE_0; /* TODO: Is this appropriate for right here? */
 	if (spi->max_speed_hz > MAX_SPI_SPEED_HZ)
 		spi->max_speed_hz = MAX_SPI_SPEED_HZ;
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index d37bfcf..964a1c2 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -83,4 +83,23 @@ config OF_MTD
 	depends on MTD
 	def_bool y
 
+config OF_RESOLVE
+	bool "OF Dynamic resolution support"
+	depends on OF
+	select OF_DYNAMIC
+	select OF_DEVICE
+	help
+	  Enable OF dynamic resolution support. This allows you to
+	  load Device Tree object fragments are run time.
+
+config OF_OVERLAY
+	bool "OF overlay support"
+	depends on OF
+	select OF_DYNAMIC
+	select OF_DEVICE
+	select OF_RESOLVE
+	help
+	  OpenFirmware overlay support. Allows you to modify on runtime the
+	  live tree using overlays.
+
 endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index e027f44..307ceb6 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -1,4 +1,4 @@
-obj-y = base.o
+obj-y = base.o dma.o util.o
 obj-$(CONFIG_OF_FLATTREE) += fdt.o
 obj-$(CONFIG_OF_PROMTREE) += pdt.o
 obj-$(CONFIG_OF_ADDRESS)  += address.o
@@ -11,3 +11,5 @@ obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
 obj-$(CONFIG_OF_PCI)	+= of_pci.o
 obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
 obj-$(CONFIG_OF_MTD)	+= of_mtd.o
+obj-$(CONFIG_OF_RESOLVE)  += resolver.o
+obj-$(CONFIG_OF_OVERLAY) += overlay.o
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 2390ddb..5ebfc33 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1115,7 +1115,7 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na
 EXPORT_SYMBOL(of_parse_phandle_with_args);
 
 #if defined(CONFIG_OF_DYNAMIC)
-static int of_property_notify(int action, struct device_node *np,
+int of_property_notify(int action, struct device_node *np,
 			      struct property *prop)
 {
 	struct of_prop_reconfig pr;
@@ -1124,13 +1124,62 @@ static int of_property_notify(int action, struct device_node *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)
+#endif
+
+#ifdef CONFIG_PROC_DEVICETREE
+
+void of_add_proc_dt_entry(struct device_node *dn)
 {
-	return 0;
+	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);
+}
+
+void of_remove_proc_dt_entry(struct device_node *dn)
+{
+	struct device_node *parent;
+	struct property *prop;
+
+	if (!dn)
+		return;
+
+	parent = dn->parent;
+	prop = dn->properties;
+	while (prop) {
+		if (dn->pde)
+			remove_proc_entry(prop->name, dn->pde);
+		prop = prop->next;
+	}
+
+	if (dn->pde)
+		remove_proc_entry(dn->pde->name,
+				parent ? parent->pde : NULL);
+}
+
+void of_add_proc_dt_prop_entry(struct device_node *np,
+		struct property *prop)
+{
+	if (np && prop && np->pde)
+		proc_device_tree_add_prop(np->pde, prop);
+}
+
+void of_remove_proc_dt_prop_entry(struct device_node *np,
+		struct property *prop)
+{
+	if (np && prop && np->pde)
+		proc_device_tree_remove_prop(np->pde, prop);
+}
+
+void of_update_proc_dt_prop_entry(struct device_node *np,
+		struct property *newprop, struct property *oldprop)
+{
+	if (np && newprop && oldprop && np->pde)
+		proc_device_tree_update_prop(np->pde, newprop, oldprop);
 }
-#endif
+
+#endif /* CONFIG_PROC_DEVICETREE */
 
 /**
  * of_add_property - Add a property to a node
@@ -1159,11 +1208,8 @@ int of_add_property(struct device_node *np, struct property *prop)
 	*next = prop;
 	write_unlock_irqrestore(&devtree_lock, flags);
 
-#ifdef CONFIG_PROC_DEVICETREE
 	/* try to add to proc as well if it was initialized */
-	if (np->pde)
-		proc_device_tree_add_prop(np->pde, prop);
-#endif /* CONFIG_PROC_DEVICETREE */
+	of_add_proc_dt_prop_entry(np, prop);
 
 	return 0;
 }
@@ -1205,11 +1251,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
 	if (!found)
 		return -ENODEV;
 
-#ifdef CONFIG_PROC_DEVICETREE
-	/* try to remove the proc node as well */
-	if (np->pde)
-		proc_device_tree_remove_prop(np->pde, prop);
-#endif /* CONFIG_PROC_DEVICETREE */
+	of_remove_proc_dt_prop_entry(np, prop);
 
 	return 0;
 }
@@ -1259,11 +1301,8 @@ int of_update_property(struct device_node *np, struct property *newprop)
 	if (!found)
 		return -ENODEV;
 
-#ifdef CONFIG_PROC_DEVICETREE
 	/* try to add to proc as well if it was initialized */
-	if (np->pde)
-		proc_device_tree_update_prop(np->pde, newprop, oldprop);
-#endif /* CONFIG_PROC_DEVICETREE */
+	of_update_proc_dt_prop_entry(np, newprop, oldprop);
 
 	return 0;
 }
@@ -1299,22 +1338,6 @@ int of_reconfig_notify(unsigned long action, void *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.
  */
@@ -1332,33 +1355,13 @@ int of_attach_node(struct device_node *np)
 	np->allnext = of_allnodes;
 	np->parent->child = np;
 	of_allnodes = np;
+	of_node_clear_flag(np, OF_DETACHED);
 	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.
  *
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 4c74e4f..d75fcaf 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -62,6 +62,9 @@ int of_device_add(struct platform_device *ofdev)
 	if (!ofdev->dev.parent)
 		set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->dev.of_node));
 
+	/* make sure we add the resources to the appropriate lists */
+	platform_device_link_resources(ofdev);
+
 	return device_add(&ofdev->dev);
 }
 
diff --git a/drivers/of/dma.c b/drivers/of/dma.c
new file mode 100644
index 0000000..19ad37c
--- /dev/null
+++ b/drivers/of/dma.c
@@ -0,0 +1,219 @@
+/*
+ * 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);
+
+/**
+ * of_dma_find_controller - Find a DMA controller in DT DMA helpers list
+ * @np:		device node of DMA controller
+ */
+static struct of_dma *of_dma_find_controller(struct device_node *np)
+{
+	struct of_dma *ofdma;
+
+	if (list_empty(&of_dma_list)) {
+		pr_err("empty DMA controller list\n");
+		return NULL;
+	}
+
+	list_for_each_entry_rcu(ofdma, &of_dma_list, of_dma_controllers)
+		if (ofdma->of_node == np)
+			return ofdma;
+
+	return NULL;
+}
+
+/**
+ * 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;
+
+	/* Now queue of_dma controller structure in list */
+	list_add_tail_rcu(&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.
+ */
+void of_dma_controller_free(struct device_node *np)
+{
+	struct of_dma *ofdma;
+
+	ofdma = of_dma_find_controller(np);
+	if (ofdma) {
+		list_del_rcu(&ofdma->of_dma_controllers);
+		kfree(ofdma);
+	}
+}
+EXPORT_SYMBOL_GPL(of_dma_controller_free);
+
+/**
+ * of_dma_find_channel - Find a DMA channel by name
+ * @np:		device node to look for DMA channels
+ * @name:	name of desired channel
+ * @dma_spec:	pointer to DMA specifier as found in the device tree
+ *
+ * Find a DMA channel by the name. Returns 0 on success or appropriate
+ * errno value on error.
+ */
+static int of_dma_find_channel(struct device_node *np, char *name,
+			       struct of_phandle_args *dma_spec)
+{
+	int count, i;
+	const char *s;
+
+	count = of_property_count_strings(np, "dma-names");
+	if (count < 0)
+		return count;
+
+	for (i = 0; i < count; i++) {
+		if (of_property_read_string_index(np, "dma-names", i, &s))
+			continue;
+
+		if (strcmp(name, s))
+			continue;
+
+		if (!of_parse_phandle_with_args(np, "dmas", "#dma-cells", i,
+						dma_spec))
+			return 0;
+	}
+
+	return -ENODEV;
+}
+
+/**
+ * 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			r;
+
+	if (!np || !name) {
+		pr_err("%s: not enough information provided\n", __func__);
+		return NULL;
+	}
+
+	do {
+		r = of_dma_find_channel(np, name, &dma_spec);
+		if (r) {
+			pr_err("%s: can't find DMA channel\n", np->full_name);
+			return NULL;
+		}
+
+		ofdma = of_dma_find_controller(dma_spec.np);
+		if (!ofdma) {
+			pr_debug("%s: can't find DMA controller %s\n",
+				 np->full_name, dma_spec.np->full_name);
+			continue;
+		}
+
+		if (dma_spec.args_count != ofdma->of_dma_nbcells) {
+			pr_debug("%s: wrong #dma-cells for %s\n", np->full_name,
+				 dma_spec.np->full_name);
+			continue;
+		}
+
+		chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
+
+		of_node_put(dma_spec.np);
+
+	} while (!chan);
+
+	return chan;
+}
+
+/**
+ * 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/of_i2c.c b/drivers/of/of_i2c.c
index b667264..116a5e0 100644
--- a/drivers/of/of_i2c.c
+++ b/drivers/of/of_i2c.c
@@ -17,10 +17,64 @@
 #include <linux/of_i2c.h>
 #include <linux/of_irq.h>
 #include <linux/module.h>
+#include <linux/err.h>
+
+struct i2c_client *
+of_i2c_register_device(struct i2c_adapter *adap,
+		struct device_node *node)
+{
+	struct i2c_client *result;
+	struct i2c_board_info info = {};
+	struct dev_archdata dev_ad = {};
+	const __be32 *addr;
+	int len;
+
+	dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);
+
+	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);
+		return ERR_PTR(-EINVAL);
+	}
+
+	addr = of_get_property(node, "reg", &len);
+	if (!addr || (len < sizeof(int))) {
+		dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
+			node->full_name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	info.addr = be32_to_cpup(addr);
+	if (info.addr > (1 << 10) - 1) {
+		dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
+			info.addr, node->full_name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	info.irq = irq_of_parse_and_map(node, 0);
+	info.of_node = of_node_get(node);
+	info.archdata = &dev_ad;
+
+	if (of_get_property(node, "wakeup-source", NULL))
+		info.flags |= I2C_CLIENT_WAKE;
+
+	request_module("%s%s", I2C_MODULE_PREFIX, info.type);
+
+	result = i2c_new_device(adap, &info);
+	if (result == NULL) {
+		dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
+			node->full_name);
+		of_node_put(node);
+		irq_dispose_mapping(info.irq);
+		return ERR_PTR(-ENODEV);
+	}
+
+	return result;
+}
+EXPORT_SYMBOL(of_i2c_register_device);
 
 void of_i2c_register_devices(struct i2c_adapter *adap)
 {
-	void *result;
 	struct device_node *node;
 
 	/* Only register child devices if the adapter has a node pointer set */
@@ -29,52 +83,8 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
 
 	dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
 
-	for_each_available_child_of_node(adap->dev.of_node, node) {
-		struct i2c_board_info info = {};
-		struct dev_archdata dev_ad = {};
-		const __be32 *addr;
-		int len;
-
-		dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);
-
-		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);
-			continue;
-		}
-
-		addr = of_get_property(node, "reg", &len);
-		if (!addr || (len < sizeof(int))) {
-			dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
-				node->full_name);
-			continue;
-		}
-
-		info.addr = be32_to_cpup(addr);
-		if (info.addr > (1 << 10) - 1) {
-			dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
-				info.addr, node->full_name);
-			continue;
-		}
-
-		info.irq = irq_of_parse_and_map(node, 0);
-		info.of_node = of_node_get(node);
-		info.archdata = &dev_ad;
-
-		if (of_get_property(node, "wakeup-source", NULL))
-			info.flags |= I2C_CLIENT_WAKE;
-
-		request_module("%s%s", I2C_MODULE_PREFIX, info.type);
-
-		result = i2c_new_device(adap, &info);
-		if (result == NULL) {
-			dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
-			        node->full_name);
-			of_node_put(node);
-			irq_dispose_mapping(info.irq);
-			continue;
-		}
-	}
+	for_each_available_child_of_node(adap->dev.of_node, node)
+		of_i2c_register_device(adap, node);
 }
 EXPORT_SYMBOL(of_i2c_register_devices);
 
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
new file mode 100644
index 0000000..f09fe56
--- /dev/null
+++ b/drivers/of/overlay.c
@@ -0,0 +1,868 @@
+/*
+ * Functions for working with device tree overlays
+ *
+ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
+ * 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
+ * version 2 as published by the Free Software Foundation.
+ */
+#undef DEBUG
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_i2c.h>
+#include <linux/i2c.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+/**
+ * Apply a single overlay node recursively.
+ *
+ * Property or node names that start with '-' signal that
+ * the property/node is to be removed.
+ *
+ * All the property notifiers are appropriately called.
+ * Note that the in case of an error the target node is left
+ * in a inconsistent state. Error recovery should be performed
+ * by recording the modification using the of notifiers.
+ */
+static int of_overlay_apply_one(struct device_node *target,
+		const struct device_node *overlay)
+{
+	const char *pname, *cname;
+	struct device_node *child, *tchild;
+	struct property *prop, *propn, *tprop;
+	int remove;
+	char *full_name;
+	const char *suffix;
+	int ret;
+
+	/* sanity checks */
+	if (target == NULL || overlay == NULL)
+		return -EINVAL;
+
+	for_each_property_of_node(overlay, prop) {
+
+		/* don't touch, 'name' */
+		if (of_prop_cmp(prop->name, "name") == 0)
+			continue;
+
+		/* default is add */
+		remove = 0;
+		pname = prop->name;
+		if (*pname == '-') {	/* skip, - notes removal */
+			pname++;
+			remove = 1;
+			propn = NULL;
+		} else {
+			propn = __of_copy_property(prop,
+					GFP_KERNEL);
+			if (propn == NULL)
+				return -ENOMEM;
+		}
+
+		tprop = of_find_property(target, pname, NULL);
+
+		/* found? */
+		if (tprop != NULL) {
+			if (propn != NULL)
+				ret = of_update_property(target, propn);
+			else
+				ret = of_remove_property(target, tprop);
+		} else {
+			if (propn != NULL)
+				ret = of_add_property(target, propn);
+			else
+				ret = 0;
+		}
+		if (ret != 0)
+			return ret;
+	}
+
+	__for_each_child_of_node(overlay, child) {
+
+		/* default is add */
+		remove = 0;
+		cname = child->name;
+		if (*cname == '-') {	/* skip, - notes removal */
+			cname++;
+			remove = 1;
+		}
+
+		/* special case for nodes with a suffix */
+		suffix = strrchr(child->full_name, '@');
+		if (suffix != NULL) {
+			cname = kbasename(child->full_name);
+			WARN_ON(cname == NULL);	/* sanity check */
+			if (cname == NULL)
+				continue;
+			if (*cname == '-')
+				cname++;
+		}
+
+		tchild = of_get_child_by_name(target, cname);
+		if (tchild != NULL) {
+
+			if (!remove) {
+
+				/* apply overlay recursively */
+				ret = of_overlay_apply_one(tchild, child);
+				of_node_put(tchild);
+
+				if (ret != 0)
+					return ret;
+
+			} else {
+
+				ret = of_detach_node(tchild);
+				of_node_put(tchild);
+			}
+
+		} else {
+
+			if (!remove) {
+				full_name = kasprintf(GFP_KERNEL, "%s/%s",
+						target->full_name, cname);
+				if (full_name == NULL)
+					return -ENOMEM;
+
+				/* create empty tree as a target */
+				tchild = __of_create_empty_node(cname,
+						child->type, full_name,
+						child->phandle, GFP_KERNEL);
+
+				/* free either way */
+				kfree(full_name);
+
+				if (tchild == NULL)
+					return -ENOMEM;
+
+				/* point to parent */
+				tchild->parent = target;
+
+				ret = of_attach_node(tchild);
+				if (ret != 0)
+					return ret;
+
+				/* apply the overlay */
+				ret = of_overlay_apply_one(tchild, child);
+				if (ret != 0) {
+					__of_free_tree(tchild);
+					return ret;
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Lookup an overlay device entry
+ */
+struct of_overlay_device_entry *of_overlay_device_entry_lookup(
+		struct of_overlay_info *ovinfo, struct device_node *node)
+{
+	struct of_overlay_device_entry *de;
+
+	/* no need for locks, we'de under the ovinfo->lock */
+	list_for_each_entry(de, &ovinfo->de_list, node) {
+		if (de->np == node)
+			return de;
+	}
+	return NULL;
+}
+
+/**
+ * Add an overlay log entry
+ */
+static int of_overlay_log_entry_entry_add(struct of_overlay_info *ovinfo,
+		unsigned long action, struct device_node *dn,
+		struct property *prop)
+{
+	struct of_overlay_log_entry *le;
+
+	/* check */
+	if (ovinfo == NULL || dn == NULL)
+		return -EINVAL;
+
+	le = kzalloc(sizeof(*le), GFP_KERNEL);
+	if (le == NULL) {
+		pr_err("%s: Failed to allocate\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* get a reference to the node */
+	le->action = action;
+	le->np = of_node_get(dn);
+	le->prop = prop;
+
+	if (action == OF_RECONFIG_UPDATE_PROPERTY && prop)
+		le->old_prop = of_find_property(dn, prop->name, NULL);
+
+	list_add_tail(&le->node, &ovinfo->le_list);
+
+	return 0;
+}
+
+/**
+ * Add an overlay device entry
+ */
+static void of_overlay_device_entry_entry_add(struct of_overlay_info *ovinfo,
+		struct device_node *node,
+		struct platform_device *pdev, struct i2c_client *client,
+		int prevstate, int state)
+{
+	struct of_overlay_device_entry *de;
+	int fresh;
+
+	/* check */
+	if (ovinfo == NULL)
+		return;
+
+	fresh = 0;
+	de = of_overlay_device_entry_lookup(ovinfo, node);
+	if (de == NULL) {
+		de = kzalloc(sizeof(*de), GFP_KERNEL);
+		if (de == NULL) {
+			pr_err("%s: Failed to allocate\n", __func__);
+			return;
+		}
+		fresh = 1;
+		de->prevstate = -1;
+	}
+
+	if (de->np == NULL)
+		de->np = of_node_get(node);
+	if (de->pdev == NULL && pdev)
+		de->pdev = of_dev_get(pdev);
+	if (de->client == NULL && client)
+		de->client = i2c_use_client(client);
+	if (fresh)
+		de->prevstate = prevstate;
+	de->state = state;
+
+	if (fresh)
+		list_add_tail(&de->node, &ovinfo->de_list);
+}
+
+/**
+ * Overlay OF notifier
+ *
+ * Called every time there's a property/node modification
+ * Every modification causes a log entry addition, while
+ * any modification that causes a node's state to change
+ * from/to disabled to/from enabled causes a device entry
+ * addition.
+ */
+static int of_overlay_notify(struct notifier_block *nb,
+				unsigned long action, void *arg)
+{
+	struct of_overlay_info *ovinfo;
+	struct device_node *node;
+	struct property *prop, *sprop, *cprop;
+	struct of_prop_reconfig *pr;
+	struct platform_device *pdev;
+	struct i2c_client *client;
+	struct device_node *tnode;
+	int depth;
+	int prevstate, state;
+	int err = 0;
+
+	ovinfo = container_of(nb, struct of_overlay_info, notifier);
+
+	/* prep vars */
+	switch (action) {
+	case OF_RECONFIG_ATTACH_NODE:
+	case OF_RECONFIG_DETACH_NODE:
+		node = arg;
+		if (node == NULL)
+			return notifier_from_errno(-EINVAL);
+		prop = NULL;
+		break;
+	case OF_RECONFIG_ADD_PROPERTY:
+	case OF_RECONFIG_REMOVE_PROPERTY:
+	case OF_RECONFIG_UPDATE_PROPERTY:
+		pr = arg;
+		if (pr == NULL)
+			return notifier_from_errno(-EINVAL);
+		node = pr->dn;
+		if (node == NULL)
+			return notifier_from_errno(-EINVAL);
+		prop = pr->prop;
+		if (prop == NULL)
+			return notifier_from_errno(-EINVAL);
+		break;
+	default:
+		return notifier_from_errno(0);
+	}
+
+	/* add to the log */
+	err = of_overlay_log_entry_entry_add(ovinfo, action, node, prop);
+	if (err != 0)
+		return notifier_from_errno(err);
+
+	/* come up with the device entry (if any) */
+	pdev = NULL;
+	client = NULL;
+	state = 0;
+	prevstate = 0;
+
+	/* determine the state the node will end up */
+	switch (action) {
+	case OF_RECONFIG_ATTACH_NODE:
+		/* we demand that a compatible node is present */
+		state = of_find_property(node, "compatible", NULL) &&
+			of_device_is_available(node);
+		break;
+	case OF_RECONFIG_DETACH_NODE:
+		prevstate = of_find_property(node, "compatible", NULL) &&
+			of_device_is_available(node);
+		state = 0;
+		pdev = of_find_device_by_node(node);
+		client = of_find_i2c_device_by_node(node);
+		break;
+	case OF_RECONFIG_ADD_PROPERTY:
+	case OF_RECONFIG_REMOVE_PROPERTY:
+	case OF_RECONFIG_UPDATE_PROPERTY:
+		/* either one cause a change in state */
+		if (strcmp(prop->name, "status") != 0 &&
+				strcmp(prop->name, "compatible") != 0)
+			return notifier_from_errno(0);
+
+		if (strcmp(prop->name, "status") == 0) {
+			/* status */
+			cprop = of_find_property(node, "compatible", NULL);
+			sprop = action != OF_RECONFIG_REMOVE_PROPERTY ?
+				prop : NULL;
+		} else {
+			/* compatible */
+			sprop = of_find_property(node, "status", NULL);
+			cprop = action != OF_RECONFIG_REMOVE_PROPERTY ?
+				prop : NULL;
+		}
+
+		prevstate = of_find_property(node, "compatible", NULL) &&
+			of_device_is_available(node);
+		state = cprop && cprop->length > 0 &&
+			    (!sprop || (sprop->length > 0 &&
+				(strcmp(sprop->value, "okay") == 0 ||
+				 strcmp(sprop->value, "ok") == 0)));
+		break;
+
+	default:
+		return notifier_from_errno(0);
+	}
+
+	/* find depth */
+	depth = 1;
+	tnode = node;
+	while (tnode != NULL && tnode != ovinfo->target) {
+		tnode = tnode->parent;
+		depth++;
+	}
+
+	/* respect overlay's maximum depth */
+	if (ovinfo->device_depth != 0 && depth > ovinfo->device_depth) {
+		pr_debug("OF: skipping device creation for node=%s depth=%d\n",
+				node->name, depth);
+		goto out;
+	}
+
+	if (state == 0) {
+		pdev = of_find_device_by_node(node);
+		client = of_find_i2c_device_by_node(node);
+	}
+
+	of_overlay_device_entry_entry_add(ovinfo, node, pdev, client,
+			prevstate, state);
+out:
+
+	return notifier_from_errno(err);
+}
+
+/**
+ * Prepare for the overlay, for now it just registers the
+ * notifier.
+ */
+static int of_overlay_prep_one(struct of_overlay_info *ovinfo)
+{
+	int err;
+
+	err = of_reconfig_notifier_register(&ovinfo->notifier);
+	if (err != 0) {
+		pr_err("%s: failed to register notifier for '%s'\n",
+			__func__, ovinfo->target->full_name);
+		return err;
+	}
+	return 0;
+}
+
+static int of_overlay_device_entry_change(struct of_overlay_info *ovinfo,
+		struct of_overlay_device_entry *de, int revert)
+{
+	struct i2c_adapter *adap = NULL;
+	struct i2c_client *client;
+	struct platform_device *pdev, *parent_pdev = NULL;
+	int state;
+
+	state = !!de->state ^ !!revert;
+
+	if (de->np && de->np->parent) {
+		pr_debug("%s: parent is %s\n",
+				__func__, de->np->parent->full_name);
+		adap = of_find_i2c_adapter_by_node(de->np->parent);
+		if (adap == NULL)
+			parent_pdev = of_find_device_by_node(de->np->parent);
+	}
+
+	if (state) {
+
+		/* try to see if it's an I2C client node */
+		if (adap == NULL) {
+
+			pr_debug("%s: creating new platform device "
+					"new_node='%s' %p\n",
+					__func__, de->np->full_name, de->np);
+
+			pdev = of_platform_device_create(de->np, NULL,
+					parent_pdev ? &parent_pdev->dev : NULL);
+			if (pdev == NULL) {
+				pr_warn("%s: Failed to create platform device "
+						"for '%s'\n",
+						__func__, de->np->full_name);
+			} else
+				de->pdev = pdev;
+
+		} else {
+
+			client = of_find_i2c_device_by_node(de->np);
+			if (client != NULL) {
+				/* bus already created the device; do nothing */
+				put_device(&client->dev);
+			} else {
+				pr_debug("%s: creating new i2c_client device "
+						"new_node='%s' %p\n",
+						__func__, de->np->full_name, de->np);
+
+				client = of_i2c_register_device(adap, de->np);
+
+				if (client == NULL) {
+					pr_warn("%s: Failed to create i2c client device "
+							"for '%s'\n",
+							__func__, de->np->full_name);
+				} else
+					de->client = client;
+			}
+		}
+
+	} else {
+
+		if (de->pdev) {
+			pr_debug("%s: removing pdev %s\n", __func__,
+					dev_name(&de->pdev->dev));
+			platform_device_unregister(de->pdev);
+			de->pdev = NULL;
+		}
+
+		if (de->client) {
+			pr_debug("%s: removing i2c client %s\n", __func__,
+					dev_name(&de->client->dev));
+			i2c_unregister_device(de->client);
+			de->client = NULL;
+		}
+	}
+
+	if (adap)
+		put_device(&adap->dev);
+
+	if (parent_pdev)
+		of_dev_put(parent_pdev);
+
+	return 0;
+}
+
+/**
+ * Revert one overlay
+ * Either due to an error, or due to normal overlay removal.
+ * Using the log entries, we revert any change to the live tree.
+ * In the same manner, using the device entries we enable/disable
+ * the platform devices appropriately.
+ */
+static void of_overlay_revert_one(struct of_overlay_info *ovinfo)
+{
+	struct of_overlay_device_entry *de, *den;
+	struct of_overlay_log_entry *le, *len;
+	struct property *prop, **propp;
+	int ret;
+	unsigned long flags;
+
+	if (!ovinfo || !ovinfo->target || !ovinfo->overlay)
+		return;
+
+	pr_debug("%s: Reverting overlay on '%s'\n", __func__,
+			ovinfo->target->full_name);
+
+	/* overlay applied correctly, now create/destroy pdevs */
+	list_for_each_entry_safe_reverse(de, den, &ovinfo->de_list, node) {
+		of_overlay_device_entry_change(ovinfo, de, 1);
+		of_node_put(de->np);
+		list_del(&de->node);
+		kfree(de);
+	}
+
+	list_for_each_entry_safe_reverse(le, len, &ovinfo->le_list, node) {
+
+		ret = 0;
+		switch (le->action) {
+		case OF_RECONFIG_ATTACH_NODE:
+			pr_debug("Reverting ATTACH_NODE %s\n",
+					le->np->full_name);
+			ret = of_detach_node(le->np);
+			break;
+
+		case OF_RECONFIG_DETACH_NODE:
+			pr_debug("Reverting DETACH_NODE %s\n",
+					le->np->full_name);
+			ret = of_attach_node(le->np);
+			break;
+
+		case OF_RECONFIG_ADD_PROPERTY:
+			pr_debug("Reverting ADD_PROPERTY %s %s\n",
+					le->np->full_name, le->prop->name);
+			ret = of_remove_property(le->np, le->prop);
+			break;
+
+		case OF_RECONFIG_REMOVE_PROPERTY:
+		case OF_RECONFIG_UPDATE_PROPERTY:
+
+			pr_debug("Reverting %s_PROPERTY %s %s\n",
+				le->action == OF_RECONFIG_REMOVE_PROPERTY ?
+					"REMOVE" : "UPDATE",
+					le->np->full_name, le->prop->name);
+
+			/* property is possibly on deadprops (avoid alloc) */
+			write_lock_irqsave(&devtree_lock, flags);
+			prop = le->action == OF_RECONFIG_REMOVE_PROPERTY ?
+				le->prop : le->old_prop;
+			propp = &le->np->deadprops;
+			while (*propp != NULL) {
+				if (*propp == prop)
+					break;
+				propp = &(*propp)->next;
+			}
+			if (*propp != NULL) {
+				/* remove it from deadprops */
+				(*propp)->next = prop->next;
+				write_unlock_irqrestore(&devtree_lock, flags);
+			} else {
+				write_unlock_irqrestore(&devtree_lock, flags);
+				/* not found, just make a copy */
+				prop = __of_copy_property(prop, GFP_KERNEL);
+				if (prop == NULL) {
+					pr_err("%s: Failed to copy property\n",
+							__func__);
+					break;
+				}
+			}
+
+			if (le->action == OF_RECONFIG_REMOVE_PROPERTY)
+				ret = of_add_property(le->np, prop);
+			else
+				ret = of_update_property(le->np, prop);
+			break;
+
+		default:
+			/* nothing */
+			break;
+		}
+
+		if (ret != 0)
+			pr_err("%s: revert on node %s Failed!\n",
+					__func__, le->np->full_name);
+
+		of_node_put(le->np);
+
+		list_del(&le->node);
+
+		kfree(le);
+	}
+}
+
+/**
+ * Perform the post overlay work.
+ *
+ * We unregister the notifier, and in the case on an error we
+ * revert the overlay.
+ * If the overlay applied correctly, we iterare over the device entries
+ * and create/destroy the platform devices appropriately.
+ */
+static int of_overlay_post_one(struct of_overlay_info *ovinfo, int err)
+{
+	struct of_overlay_device_entry *de, *den;
+
+	of_reconfig_notifier_unregister(&ovinfo->notifier);
+
+	if (err != 0) {
+		/* revert this (possible partially applied) overlay */
+		of_overlay_revert_one(ovinfo);
+		return 0;
+	}
+
+	/* overlay applied correctly, now create/destroy pdevs */
+	list_for_each_entry_safe(de, den, &ovinfo->de_list, node) {
+
+		/* no state change? just remove this entry */
+		if (de->prevstate == de->state) {
+			of_node_put(de->np);
+			list_del(&de->node);
+			kfree(de);
+		} else {
+			of_overlay_device_entry_change(ovinfo, de, 0);
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * of_overlay	- Apply @count overlays pointed at by @ovinfo_tab
+ * @count:	Number of of_overlay_info's
+ * @ovinfo_tab:	Array of overlay_info's to apply
+ *
+ * Applies the overlays given, while handling all error conditions
+ * appropriately. Either the operation succeeds, or if it fails the
+ * live tree is reverted to the state before the attempt.
+ * Returns 0, or an error if the overlay attempt failed.
+ */
+int of_overlay(int count, struct of_overlay_info *ovinfo_tab)
+{
+	struct of_overlay_info *ovinfo;
+	int i, err;
+
+	if (!ovinfo_tab)
+		return -EINVAL;
+
+	/* first we apply the overlays atomically */
+	for (i = 0; i < count; i++) {
+
+		ovinfo = &ovinfo_tab[i];
+
+		mutex_lock(&ovinfo->lock);
+
+		err = of_overlay_prep_one(ovinfo);
+		if (err == 0)
+			err = of_overlay_apply_one(ovinfo->target,
+					ovinfo->overlay);
+		of_overlay_post_one(ovinfo, err);
+
+		mutex_unlock(&ovinfo->lock);
+
+		if (err != 0) {
+			pr_err("%s: overlay failed '%s'\n",
+				__func__, ovinfo->target->full_name);
+			goto err_fail;
+		}
+	}
+
+	return 0;
+
+err_fail:
+	while (--i >= 0) {
+		ovinfo = &ovinfo_tab[i];
+
+		mutex_lock(&ovinfo->lock);
+		of_overlay_revert_one(ovinfo);
+		mutex_unlock(&ovinfo->lock);
+	}
+
+	return err;
+}
+
+/**
+ * of_overlay_revert	- Revert a previously applied overlay
+ * @count:	Number of of_overlay_info's
+ * @ovinfo_tab:	Array of overlay_info's to apply
+ *
+ * Revert a previous overlay. The state of the live tree
+ * is reverted to the one before the overlay.
+ * Returns 0, or an error if the overlay table is not given.
+ */
+int of_overlay_revert(int count, struct of_overlay_info *ovinfo_tab)
+{
+	struct of_overlay_info *ovinfo;
+	int i;
+
+	if (!ovinfo_tab)
+		return -EINVAL;
+
+	/* revert the overlays in reverse */
+	for (i = count - 1; i >= 0; i--) {
+
+		ovinfo = &ovinfo_tab[i];
+
+		mutex_lock(&ovinfo->lock);
+		of_overlay_revert_one(ovinfo);
+		mutex_unlock(&ovinfo->lock);
+
+	}
+
+	return 0;
+}
+
+/**
+ * of_init_overlay_info	- Initialize a single of_overlay_info structure
+ * @ovinfo:	Pointer to the overlay info structure to initialize
+ *
+ * Initialize a single overlay info structure.
+ */
+void of_init_overlay_info(struct of_overlay_info *ovinfo)
+{
+	memset(ovinfo, 0, sizeof(ovinfo));
+	mutex_init(&ovinfo->lock);
+	INIT_LIST_HEAD(&ovinfo->de_list);
+	INIT_LIST_HEAD(&ovinfo->le_list);
+
+	ovinfo->notifier.notifier_call = of_overlay_notify;
+}
+
+/**
+ * of_fill_overlay_info	- Fill an overlay info structure
+ * @info_node:	Device node containing the overlay
+ * @ovinfo:	Pointer to the overlay info structure to fill
+ *
+ * Fills an overlay info structure with the overlay information
+ * from a device node. This device node must have a target property
+ * which contains a phandle of the overlay target node, and an
+ * __overlay__ child node which has the overlay contents.
+ * Both ovinfo->target & ovinfo->overlay have their references taken.
+ *
+ * Returns 0 on success, or a negative error value.
+ */
+int of_fill_overlay_info(struct device_node *info_node,
+		struct of_overlay_info *ovinfo)
+{
+	u32 val;
+	int ret;
+
+	if (!info_node || !ovinfo)
+		return -EINVAL;
+
+	ret = of_property_read_u32(info_node, "target", &val);
+	if (ret != 0)
+		goto err_fail;
+
+	ovinfo->target = of_find_node_by_phandle(val);
+	if (ovinfo->target == NULL)
+		goto err_fail;
+
+	ovinfo->overlay = of_get_child_by_name(info_node, "__overlay__");
+	if (ovinfo->overlay == NULL)
+		goto err_fail;
+
+	ret = of_property_read_u32(info_node, "depth", &val);
+	if (ret == 0)
+		ovinfo->device_depth = val;
+	else
+		ovinfo->device_depth = 0;
+
+
+	return 0;
+
+err_fail:
+	of_node_put(ovinfo->target);
+	of_node_put(ovinfo->overlay);
+
+	memset(ovinfo, 0, sizeof(*ovinfo));
+	return -EINVAL;
+}
+
+/**
+ * of_build_overlay_info	- Build an overlay info array
+ * @tree:	Device node containing all the overlays
+ * @cntp:	Pointer to where the overlay info count will be help
+ * @ovinfop:	Pointer to the pointer of an overlay info structure.
+ *
+ * Helper function that given a tree containing overlay information,
+ * allocates and builds an overlay info array containing it, ready
+ * for use using of_overlay.
+ *
+ * Returns 0 on success with the @cntp @ovinfop pointers valid,
+ * while on error a negative error value is returned.
+ */
+int of_build_overlay_info(struct device_node *tree,
+		int *cntp, struct of_overlay_info **ovinfop)
+{
+	struct device_node *node;
+	struct of_overlay_info *ovinfo;
+	int cnt, err;
+
+	if (tree == NULL || cntp == NULL || ovinfop == NULL)
+		return -EINVAL;
+
+	/* worst case; every child is a node */
+	cnt = 0;
+	for_each_child_of_node(tree, node)
+		cnt++;
+
+	ovinfo = kzalloc(cnt * sizeof(*ovinfo), GFP_KERNEL);
+	if (ovinfo == NULL)
+		return -ENOMEM;
+
+	cnt = 0;
+	for_each_child_of_node(tree, node) {
+
+		of_init_overlay_info(&ovinfo[cnt]);
+		err = of_fill_overlay_info(node, &ovinfo[cnt]);
+		if (err == 0)
+			cnt++;
+	}
+
+	/* if nothing filled, return error */
+	if (cnt == 0) {
+		kfree(ovinfo);
+		return -ENODEV;
+	}
+
+	*cntp = cnt;
+	*ovinfop = ovinfo;
+
+	return 0;
+}
+
+/**
+ * of_free_overlay_info	- Free an overlay info array
+ * @count:	Number of of_overlay_info's
+ * @ovinfo_tab:	Array of overlay_info's to free
+ *
+ * Releases the memory of a previously allocate ovinfo array
+ * by of_build_overlay_info.
+ * Returns 0, or an error if the arguments are bogus.
+ */
+int of_free_overlay_info(int count, struct of_overlay_info *ovinfo_tab)
+{
+	struct of_overlay_info *ovinfo;
+	int i;
+
+	if (!ovinfo_tab || count < 0)
+		return -EINVAL;
+
+	/* do it in reverse */
+	for (i = count - 1; i >= 0; i--) {
+		ovinfo = &ovinfo_tab[i];
+
+		of_node_put(ovinfo->target);
+		of_node_put(ovinfo->overlay);
+	}
+	kfree(ovinfo_tab);
+
+	return 0;
+}
+
diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
new file mode 100644
index 0000000..016d7da
--- /dev/null
+++ b/drivers/of/resolver.c
@@ -0,0 +1,394 @@
+/*
+ * Functions for dealing with DT resolution
+ *
+ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
+ * 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
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_fdt.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/**
+ * Find a subtree's maximum phandle value.
+ */
+static phandle __of_get_tree_max_phandle(struct device_node *node,
+		phandle max_phandle)
+{
+	struct device_node *child;
+
+	if (node->phandle != 0 && node->phandle != OF_PHANDLE_ILLEGAL &&
+			node->phandle > max_phandle)
+		max_phandle = node->phandle;
+
+	__for_each_child_of_node(node, child)
+		max_phandle = __of_get_tree_max_phandle(child, max_phandle);
+
+	return max_phandle;
+}
+
+/**
+ * Find live tree's maximum phandle value.
+ */
+static phandle of_get_tree_max_phandle(void)
+{
+	struct device_node *node;
+	phandle phandle;
+
+	/* get root node */
+	node = of_find_node_by_path("/");
+	if (node == NULL)
+		return OF_PHANDLE_ILLEGAL;
+
+	/* now search recursively */
+	read_lock(&devtree_lock);
+	phandle = __of_get_tree_max_phandle(node, 0);
+	read_unlock(&devtree_lock);
+
+	of_node_put(node);
+
+	return phandle;
+}
+
+/**
+ * Adjust a subtree's phandle values by a given delta.
+ * Makes sure not to just adjust the device node's phandle value,
+ * but modify the phandle properties values as well.
+ */
+static void __of_adjust_tree_phandles(struct device_node *node,
+		int phandle_delta)
+{
+	struct device_node *child;
+	struct property *prop;
+	phandle phandle;
+
+	/* first adjust the node's phandle direct value */
+	if (node->phandle != 0 && node->phandle != OF_PHANDLE_ILLEGAL)
+		node->phandle += phandle_delta;
+
+	/* now adjust phandle & linux,phandle values */
+	for_each_property_of_node(node, prop) {
+
+		/* only look for these two */
+		if (of_prop_cmp(prop->name, "phandle") != 0 &&
+		    of_prop_cmp(prop->name, "linux,phandle") != 0)
+			continue;
+
+		/* must be big enough */
+		if (prop->length < 4)
+			continue;
+
+		/* read phandle value */
+		phandle = be32_to_cpu(*(uint32_t *)prop->value);
+		if (phandle == OF_PHANDLE_ILLEGAL)	/* unresolved */
+			continue;
+
+		/* adjust */
+		*(uint32_t *)prop->value = cpu_to_be32(node->phandle);
+	}
+
+	/* now do the children recursively */
+	__for_each_child_of_node(node, child)
+		__of_adjust_tree_phandles(child, phandle_delta);
+}
+
+/**
+ * Adjust the local phandle references by the given phandle delta.
+ * Assumes the existances of a __local_fixups__ node at the root
+ * of the tree. Does not take any devtree locks so make sure you
+ * call this on a tree which is at the detached state.
+ */
+static int __of_adjust_tree_phandle_references(struct device_node *node,
+		int phandle_delta)
+{
+	phandle phandle;
+	struct device_node *refnode, *child;
+	struct property *rprop, *sprop;
+	char *propval, *propcur, *propend, *nodestr, *propstr, *s;
+	int offset, propcurlen;
+	int err;
+
+	/* locate the symbols & fixups nodes on resolve */
+	__for_each_child_of_node(node, child)
+		if (of_node_cmp(child->name, "__local_fixups__") == 0)
+			break;
+
+	/* no local fixups */
+	if (child == NULL)
+		return 0;
+
+	/* find the local fixups property */
+	for_each_property_of_node(child, rprop) {
+
+		/* skip properties added automatically */
+		if (of_prop_cmp(rprop->name, "name") == 0)
+			continue;
+
+		/* make a copy */
+		propval = kmalloc(rprop->length, GFP_KERNEL);
+		if (propval == NULL) {
+			pr_err("%s: Could not copy value of '%s'\n",
+					__func__, rprop->name);
+			return -ENOMEM;
+		}
+		memcpy(propval, rprop->value, rprop->length);
+
+		propend = propval + rprop->length;
+		for (propcur = propval; propcur < propend;
+				propcur += propcurlen + 1) {
+
+			propcurlen = strlen(propcur);
+
+			nodestr = propcur;
+			s = strchr(propcur, ':');
+			if (s == NULL) {
+				pr_err("%s: Illegal symbol entry '%s' (1)\n",
+					__func__, propcur);
+				err = -EINVAL;
+				goto err_fail;
+			}
+			*s++ = '\0';
+
+			propstr = s;
+			s = strchr(s, ':');
+			if (s == NULL) {
+				pr_err("%s: Illegal symbol entry '%s' (2)\n",
+					__func__, (char *)rprop->value);
+				err = -EINVAL;
+				goto err_fail;
+			}
+
+			*s++ = '\0';
+			offset = simple_strtoul(s, NULL, 10);
+
+			/* look into the resolve node for the full path */
+			refnode = __of_find_node_by_full_name(node, nodestr);
+			if (refnode == NULL) {
+				pr_warn("%s: Could not find refnode '%s'\n",
+					__func__, (char *)rprop->value);
+				continue;
+			}
+
+			/* now find the property */
+			for_each_property_of_node(refnode, sprop) {
+				if (of_prop_cmp(sprop->name, propstr) == 0)
+					break;
+			}
+
+			if (sprop == NULL) {
+				pr_err("%s: Could not find property '%s'\n",
+					__func__, (char *)rprop->value);
+				err = -ENOENT;
+				goto err_fail;
+			}
+
+			phandle = be32_to_cpu(*(uint32_t *)
+					(sprop->value + offset));
+			*(uint32_t *)(sprop->value + offset) =
+				cpu_to_be32(phandle + phandle_delta);
+		}
+
+		kfree(propval);
+	}
+
+	return 0;
+
+err_fail:
+	kfree(propval);
+	return err;
+}
+
+/**
+ * of_resolve	- Resolve the given node against the live tree.
+ *
+ * @resolve:	Node to resolve
+ *
+ * Perform dynamic Device Tree resolution against the live tree
+ * to the given node to resolve. This depends on the live tree
+ * having a __symbols__ node, and the resolve node the __fixups__ &
+ * __local_fixups__ nodes (if needed).
+ * The result of the operation is a resolve node that it's contents
+ * are fit to be inserted or operate upon the live tree.
+ * Returns 0 on success or a negative error value on error.
+ */
+int of_resolve(struct device_node *resolve)
+{
+	struct device_node *child, *refnode;
+	struct device_node *root_sym, *resolve_sym, *resolve_fix;
+	struct property *rprop, *sprop;
+	const char *refpath;
+	char *propval, *propcur, *propend, *nodestr, *propstr, *s;
+	int offset, propcurlen;
+	phandle phandle, phandle_delta;
+	int err;
+
+	/* the resolve node must exist, and be detached */
+	if (resolve == NULL ||
+			!of_node_check_flag(resolve, OF_DETACHED)) {
+		return -EINVAL;
+	}
+
+	/* first we need to adjust the phandles */
+	phandle_delta = of_get_tree_max_phandle() + 1;
+	__of_adjust_tree_phandles(resolve, phandle_delta);
+	err = __of_adjust_tree_phandle_references(resolve, phandle_delta);
+	if (err != 0)
+		return err;
+
+	root_sym = NULL;
+	resolve_sym = NULL;
+	resolve_fix = NULL;
+
+	/* this may fail (if no fixups are required) */
+	root_sym = of_find_node_by_path("/__symbols__");
+
+	/* locate the symbols & fixups nodes on resolve */
+	__for_each_child_of_node(resolve, child) {
+
+		if (resolve_sym == NULL &&
+				of_node_cmp(child->name, "__symbols__") == 0)
+			resolve_sym = child;
+
+		if (resolve_fix == NULL &&
+				of_node_cmp(child->name, "__fixups__") == 0)
+			resolve_fix = child;
+
+		/* both found, don't bother anymore */
+		if (resolve_sym != NULL && resolve_fix != NULL)
+			break;
+	}
+
+	/* we do allow for the case where no fixups are needed */
+	if (resolve_fix == NULL)
+		goto merge_sym;
+
+	/* we need to fixup, but no root symbols... */
+	if (root_sym == NULL)
+		return -EINVAL;
+
+	for_each_property_of_node(resolve_fix, rprop) {
+
+		/* skip properties added automatically */
+		if (of_prop_cmp(rprop->name, "name") == 0)
+			continue;
+
+		err = of_property_read_string(root_sym,
+				rprop->name, &refpath);
+		if (err != 0) {
+			pr_err("%s: Could not find symbol '%s'\n",
+					__func__, rprop->name);
+			goto err_fail;
+		}
+
+		refnode = of_find_node_by_path(refpath);
+		if (refnode == NULL) {
+			pr_err("%s: Could not find node by path '%s'\n",
+					__func__, refpath);
+			err = -ENOENT;
+			goto err_fail;
+		}
+
+		phandle = refnode->phandle;
+		of_node_put(refnode);
+
+		pr_debug("%s: %s phandle is 0x%08x\n",
+				__func__, rprop->name, phandle);
+
+		/* make a copy */
+		propval = kmalloc(rprop->length, GFP_KERNEL);
+		if (propval == NULL) {
+			pr_err("%s: Could not copy value of '%s'\n",
+					__func__, rprop->name);
+			err = -ENOMEM;
+			goto err_fail;
+		}
+
+		memcpy(propval, rprop->value, rprop->length);
+
+		propend = propval + rprop->length;
+		for (propcur = propval; propcur < propend;
+				propcur += propcurlen + 1) {
+			propcurlen = strlen(propcur);
+
+			nodestr = propcur;
+			s = strchr(propcur, ':');
+			if (s == NULL) {
+				pr_err("%s: Illegal symbol "
+					"entry '%s' (1)\n",
+					__func__, (char *)rprop->value);
+				kfree(propval);
+				err = -EINVAL;
+				goto err_fail;
+			}
+			*s++ = '\0';
+
+			propstr = s;
+			s = strchr(s, ':');
+			if (s == NULL) {
+				pr_err("%s: Illegal symbol "
+					"entry '%s' (2)\n",
+					__func__, (char *)rprop->value);
+				kfree(propval);
+				err = -EINVAL;
+				goto err_fail;
+			}
+
+			*s++ = '\0';
+			offset = simple_strtoul(s, NULL, 10);
+
+			/* look into the resolve node for the full path */
+			refnode = __of_find_node_by_full_name(resolve,
+					nodestr);
+			if (refnode == NULL) {
+				pr_err("%s: Could not find refnode '%s'\n",
+					__func__, (char *)rprop->value);
+				kfree(propval);
+				err = -ENOENT;
+				goto err_fail;
+			}
+
+			/* now find the property */
+			for_each_property_of_node(refnode, sprop) {
+				if (of_prop_cmp(sprop->name, propstr) == 0)
+					break;
+			}
+
+			if (sprop == NULL) {
+				pr_err("%s: Could not find property '%s'\n",
+					__func__, (char *)rprop->value);
+				kfree(propval);
+				err = -ENOENT;
+				goto err_fail;
+			}
+
+			*(uint32_t *)(sprop->value + offset) =
+				cpu_to_be32(phandle);
+		}
+
+		kfree(propval);
+	}
+
+merge_sym:
+
+	of_node_put(root_sym);
+
+	return 0;
+
+err_fail:
+
+	if (root_sym != NULL)
+		of_node_put(root_sym);
+
+	return err;
+}
diff --git a/drivers/of/util.c b/drivers/of/util.c
new file mode 100644
index 0000000..5117e2b
--- /dev/null
+++ b/drivers/of/util.c
@@ -0,0 +1,253 @@
+/*
+ * Utility functions for working with device tree(s)
+ *
+ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
+ * 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
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+/**
+ * __of_free_property - release the memory of an allocated property
+ * @prop:	Property to release
+ *
+ * Release the memory of an allocated property only after checking
+ * that the property has been marked as OF_DYNAMIC.
+ * Only call on known allocated properties.
+ */
+void __of_free_property(struct property *prop)
+{
+	if (prop == NULL)
+		return;
+
+	if (of_property_check_flag(prop, OF_DYNAMIC)) {
+		kfree(prop->value);
+		kfree(prop->name);
+		kfree(prop);
+	} else {
+		pr_warn("%s: property %p cannot be freed; memory is gone\n",
+				__func__, prop);
+	}
+}
+
+/**
+ * __of_free_tree - release the memory of a device tree node and
+ *		    of all it's children + properties.
+ * @node:	Device Tree node to release
+ *
+ * Release the memory of a device tree node and of all it's children.
+ * Also release the properties and the dead properties.
+ * Only call on detached node trees, and you better be sure that
+ * no pointer exist for any properties. Only safe to do if you 
+ * absolutely control the life cycle of the node.
+ * Also note that the node is not removed from the all_nodes list,
+ * neither from the parent's child list; this should be handled before
+ * calling this function.
+ */
+void __of_free_tree(struct device_node *node)
+{
+	struct property *prop;
+	struct device_node *noden;
+
+	/* sanity check */
+	if (!node)
+		return;
+
+	/* free recursively any children */
+	while ((noden = node->child) != NULL) {
+		node->child = noden->sibling;
+		__of_free_tree(noden);
+	}
+
+	/* free every property already allocated */
+	while ((prop = node->properties) != NULL) {
+		node->properties = prop->next;
+		__of_free_property(prop);
+	}
+
+	/* free dead properties already allocated */
+	while ((prop = node->deadprops) != NULL) {
+		node->deadprops = prop->next;
+		__of_free_property(prop);
+	}
+
+	if (of_node_check_flag(node, OF_DYNAMIC)) {
+		kfree(node->type);
+		kfree(node->name);
+		kfree(node);
+	} else {
+		pr_warn("%s: node %p cannot be freed; memory is gone\n",
+				__func__, node);
+	}
+}
+
+/**
+ * __of_copy_property - Copy a property dynamically.
+ * @prop:	Property to copy
+ * @flags:	Allocation flags (typically pass GFP_KERNEL)
+ *
+ * Copy a property by dynamically allocating the memory of both the
+ * property stucture and the property name & contents. The property's
+ * flags have the OF_DYNAMIC bit set so that we can differentiate between
+ * dynamically allocated properties and not.
+ * Returns the newly allocated property or NULL on out of memory error.
+ */
+struct property *__of_copy_property(const struct property *prop, gfp_t flags)
+{
+	struct property *propn;
+
+	propn = kzalloc(sizeof(*prop), flags);
+	if (propn == NULL)
+		return NULL;
+
+	propn->name = kstrdup(prop->name, flags);
+	if (propn->name == NULL)
+		goto err_fail_name;
+
+	if (prop->length > 0) {
+		propn->value = kmalloc(prop->length, flags);
+		if (propn->value == NULL)
+			goto err_fail_value;
+		memcpy(propn->value, prop->value, prop->length);
+		propn->length = prop->length;
+	}
+
+	/* mark the property as dynamic */
+	of_property_set_flag(propn, OF_DYNAMIC);
+
+	return propn;
+
+err_fail_value:
+	kfree(propn->name);
+err_fail_name:
+	kfree(propn);
+	return NULL;
+}
+
+/**
+ * __of_create_empty_node - Create an empty device node dynamically.
+ * @name:	Name of the new device node
+ * @type:	Type of the new device node
+ * @full_name:	Full name of the new device node
+ * @phandle:	Phandle of the new device node
+ * @flags:	Allocation flags (typically pass GFP_KERNEL)
+ *
+ * Create an empty device tree node, suitable for further modification.
+ * The node data are dynamically allocated and all the node flags
+ * have the OF_DYNAMIC & OF_DETACHED bits set.
+ * Returns the newly allocated node or NULL on out of memory error.
+ */
+struct device_node *__of_create_empty_node(
+		const char *name, const char *type, const char *full_name,
+		phandle phandle, gfp_t flags)
+{
+	struct device_node *node;
+
+	node = kzalloc(sizeof(*node), flags);
+	if (node == NULL)
+		return NULL;
+
+	node->name = kstrdup(name, flags);
+	if (node->name == NULL)
+		goto err_return;
+
+	node->type = kstrdup(type, flags);
+	if (node->type == NULL)
+		goto err_return;
+
+	node->full_name = kstrdup(full_name, flags);
+	if (node->type == NULL)
+		goto err_return;
+
+	node->phandle = phandle;
+	kref_init(&node->kref);
+	of_node_set_flag(node, OF_DYNAMIC);
+	of_node_set_flag(node, OF_DETACHED);
+
+	return node;
+
+err_return:
+	__of_free_tree(node);
+	return NULL;
+}
+
+/**
+ * __of_find_node_by_full_name - Find a node with the full name recursively
+ * @node:	Root of the tree to perform the search
+ * @full_name:	Full name of the node to find.
+ *
+ * Find a node with the give full name by recursively following any of 
+ * the child node links.
+ * Returns the matching node, or NULL if not found.
+ * Note that the devtree lock is not taken, so this function is only
+ * safe to call on either detached trees, or when devtree lock is already
+ * taken.
+ */
+struct device_node *__of_find_node_by_full_name(struct device_node *node,
+		const char *full_name)
+{
+	struct device_node *child, *found;
+
+	if (node == NULL)
+		return NULL;
+
+	/* check */
+	if (of_node_cmp(node->full_name, full_name) == 0)
+		return node;
+
+	__for_each_child_of_node(node, child) {
+		found = __of_find_node_by_full_name(child, full_name);
+		if (found != NULL)
+			return found;
+	}
+
+	return NULL;
+}
+
+/**
+ * of_multi_prop_cmp - Check if a property matches a value
+ * @prop:	Property to check
+ * @value:	Value to check against
+ *
+ * Check whether a property matches a value, using the standard
+ * of_compat_cmp() test on each string. It is similar to the test
+ * of_device_is_compatible() makes, but it can be performed without
+ * taking the devtree_lock, which is required in some cases.
+ * Returns 0 on a match, -1 on no match.
+ */
+int of_multi_prop_cmp(const struct property *prop, const char *value)
+{
+	const char *cp;
+	int cplen, vlen, l;
+
+	if (prop == NULL || value == NULL)
+		return -1;
+
+	cp = prop->value;
+	cplen = prop->length;
+	vlen = strlen(value);
+
+	while (cplen > 0) {
+		if (of_compat_cmp(cp, value, vlen) == 0)
+			return 0;
+		l = strlen(cp) + 1;
+		cp += l;
+		cplen -= l;
+	}
+
+	return -1;
+}
+
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 5c32e88..e75d107 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1014,7 +1014,17 @@ static struct platform_driver pcs_driver = {
 	},
 };
 
-module_platform_driver(pcs_driver);
+static int __init pcs_init(void)
+{
+	return platform_driver_register(&pcs_driver);
+}
+postcore_initcall(pcs_init);
+
+static void __exit pcs_exit(void)
+{
+	platform_driver_unregister(&pcs_driver);
+}
+module_exit(pcs_exit);
 
 MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
 MODULE_DESCRIPTION("One-register-per-pin type device tree based pinctrl driver");
diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c
index 2bf0c1b..9b405b3 100644
--- a/drivers/pps/clients/pps-gpio.c
+++ b/drivers/pps/clients/pps-gpio.c
@@ -33,6 +33,8 @@
 #include <linux/pps-gpio.h>
 #include <linux/gpio.h>
 #include <linux/list.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 
 /* Info for each registered platform device */
 struct pps_gpio_device_data {
@@ -104,15 +106,62 @@ get_irqf_trigger_flags(const struct pps_gpio_platform_data *pdata)
 	return flags;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id pps_gpio_dt_ids[] = {
+	{ .compatible = "pps-gpio", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pps_gpio_dt_ids);
+
+static struct pps_gpio_platform_data *
+of_get_pps_gpio_pdata(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct pps_gpio_platform_data *pdata;
+	int ret;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return NULL;
+
+	ret = of_get_gpio(np, 0);
+	if (ret < 0) {
+		pr_err("failed to get GPIO from device tree\n");
+		return NULL;
+	}
+
+	pdata->gpio_pin = ret;
+	pdata->gpio_label = PPS_GPIO_NAME;
+
+	if (of_get_property(np, "assert-falling-edge", NULL))
+		pdata->assert_falling_edge = true;
+
+	return pdata;
+}
+#else
+static struct pps_gpio_platform_data *
+of_get_pps_gpio_pdata(struct platform_device *pdev)
+{
+	return NULL;
+}
+#endif
+
 static int pps_gpio_probe(struct platform_device *pdev)
 {
 	struct pps_gpio_device_data *data;
 	int irq;
 	int ret;
-	int err;
 	int pps_default_params;
-	const struct pps_gpio_platform_data *pdata = pdev->dev.platform_data;
+	struct pps_gpio_platform_data *pdata;
+	const struct of_device_id *match;
+
+	match = of_match_device(pps_gpio_dt_ids, &pdev->dev);
+	if (match)
+		pdev->dev.platform_data = of_get_pps_gpio_pdata(pdev);
+	pdata = pdev->dev.platform_data;
 
+	if (!pdata)
+		return -ENODEV;
 
 	/* GPIO setup */
 	ret = pps_gpio_setup(pdev);
@@ -123,15 +172,13 @@ static int pps_gpio_probe(struct platform_device *pdev)
 	irq = gpio_to_irq(pdata->gpio_pin);
 	if (irq < 0) {
 		pr_err("failed to map GPIO to IRQ: %d\n", irq);
-		err = -EINVAL;
-		goto return_error;
+		return -EINVAL;
 	}
 
 	/* allocate space for device info */
 	data = kzalloc(sizeof(struct pps_gpio_device_data), GFP_KERNEL);
 	if (data == NULL) {
-		err = -ENOMEM;
-		goto return_error;
+		return -ENOMEM;
 	}
 
 	/* initialize PPS specific parts of the bookkeeping data structure. */
@@ -152,42 +199,33 @@ static int pps_gpio_probe(struct platform_device *pdev)
 	if (data->pps == NULL) {
 		kfree(data);
 		pr_err("failed to register IRQ %d as PPS source\n", irq);
-		err = -EINVAL;
-		goto return_error;
+		return -EINVAL;
 	}
 
 	data->irq = irq;
 	data->pdata = pdata;
 
 	/* register IRQ interrupt handler */
-	ret = request_irq(irq, pps_gpio_irq_handler,
+	ret = devm_request_irq(&pdev->dev, irq, pps_gpio_irq_handler,
 			get_irqf_trigger_flags(pdata), data->info.name, data);
 	if (ret) {
 		pps_unregister_source(data->pps);
 		kfree(data);
 		pr_err("failed to acquire IRQ %d\n", irq);
-		err = -EINVAL;
-		goto return_error;
+		return -EINVAL;
 	}
 
 	platform_set_drvdata(pdev, data);
 	dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n", irq);
 
 	return 0;
-
-return_error:
-	gpio_free(pdata->gpio_pin);
-	return err;
 }
 
 static int pps_gpio_remove(struct platform_device *pdev)
 {
 	struct pps_gpio_device_data *data = platform_get_drvdata(pdev);
-	const struct pps_gpio_platform_data *pdata = data->pdata;
 
 	platform_set_drvdata(pdev, NULL);
-	free_irq(data->irq, data);
-	gpio_free(pdata->gpio_pin);
 	pps_unregister_source(data->pps);
 	pr_info("removed IRQ %d as PPS source\n", data->irq);
 	kfree(data);
@@ -199,27 +237,12 @@ static struct platform_driver pps_gpio_driver = {
 	.remove		= pps_gpio_remove,
 	.driver		= {
 		.name	= PPS_GPIO_NAME,
-		.owner	= THIS_MODULE
+		.owner	= THIS_MODULE,
+		.of_match_table	= of_match_ptr(pps_gpio_dt_ids),
 	},
 };
 
-static int __init pps_gpio_init(void)
-{
-	int ret = platform_driver_register(&pps_gpio_driver);
-	if (ret < 0)
-		pr_err("failed to register platform driver\n");
-	return ret;
-}
-
-static void __exit pps_gpio_exit(void)
-{
-	platform_driver_unregister(&pps_gpio_driver);
-	pr_debug("unregistered platform driver\n");
-}
-
-module_init(pps_gpio_init);
-module_exit(pps_gpio_exit);
-
+module_platform_driver(pps_gpio_driver);
 MODULE_AUTHOR("Ricardo Martins <rasm@fe.up.pt>");
 MODULE_AUTHOR("James Nuss <jamesnuss@nanometrics.ca>");
 MODULE_DESCRIPTION("Use GPIO pin as PPS source");
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index e513cd9..3175564 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -28,6 +28,18 @@ menuconfig PWM
 
 if PWM
 
+config PWM_SYSFS
+	bool "/sys/class/pwm/... (sysfs interface)"
+	depends on SYSFS
+	help
+	  Say Y here to use a sysfs interface to control PWMs.
+
+	  For every instance of an PWM capable device there is a pwmchipX
+	  directory exported to /sys/class/pwm. If you want to use a PWM, you
+	  have to export it to sysfs, which is done by writing the number into
+	  /sys/class/pwm/export. After that /sys/class/pwm/pwmX is ready to be
+	  used.
+
 config PWM_AB8500
 	tristate "AB8500 PWM support"
 	depends on AB8500_CORE && ARCH_U8500
@@ -85,6 +97,16 @@ config PWM_MXS
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-mxs.
 
+config PWM_PCA9685
+	tristate "NXP PCA9685 PWM support"
+	depends on I2C
+	help
+	  Generic PWM framework driver for PCA9685. The PCA9685 has 16
+	  PWM controller.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pca-9685.	
+
 config PWM_PUV3
 	tristate "PKUnity NetBook-0916 PWM support"
 	depends on ARCH_PUV3
@@ -191,4 +213,15 @@ config PWM_VT8500
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-vt8500.
 
+config  EHRPWM_TEST
+	tristate "EHRPWM TEST support"
+	depends on PWM_TIEHRPWM
+
+	help
+	  Test driver support for the EHRPWM PWM driver found on AM33XX
+	  TI SOC
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm_ehrpwm.
+
 endif
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 62a2963..92ec413 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_PWM_IMX)		+= pwm-imx.o
 obj-$(CONFIG_PWM_JZ4740)	+= pwm-jz4740.o
 obj-$(CONFIG_PWM_LPC32XX)	+= pwm-lpc32xx.o
 obj-$(CONFIG_PWM_MXS)		+= pwm-mxs.o
+obj-$(CONFIG_PWM_PCA9685)	+= pwm-pca9685.o
 obj-$(CONFIG_PWM_PUV3)		+= pwm-puv3.o
 obj-$(CONFIG_PWM_PXA)		+= pwm-pxa.o
 obj-$(CONFIG_PWM_SAMSUNG)	+= pwm-samsung.o
@@ -16,3 +17,4 @@ 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
+obj-$(CONFIG_EHRPWM_TEST)	+= pwm_test.o
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 903138b..7d13e67 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -30,8 +30,6 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
-#define MAX_PWMS 1024
-
 /* flags in the third cell of the DT PWM specifier */
 #define PWM_SPEC_POLARITY	(1 << 0)
 
@@ -42,6 +40,465 @@ static LIST_HEAD(pwm_chips);
 static DECLARE_BITMAP(allocated_pwms, MAX_PWMS);
 static RADIX_TREE(pwm_tree, GFP_KERNEL);
 
+
+#ifdef CONFIG_PWM_SYSFS
+
+/* lock protects against unexport_pwm() being called while
+ * sysfs files are active.
+ */
+static DEFINE_MUTEX(sysfs_lock);
+static struct class pwm_class;
+static struct pwm_device *pwm_table[MAX_PWMS];
+
+/*
+ * /sys/class/pwm/pwm... only for PWMs that are exported
+ *   /polarity
+ *      * only visible if the underlying driver has registered a
+ *        set_polarity function
+ *      * always readable
+ *      * may be written as "1" for inverted polarity or "0" for
+ *        normal polarity
+ *      * can only be written if PWM is not running
+ *   /period_ns
+ *      * always readable
+ *      * write with desired pwm period in nanoseconds
+ *      * may return with error depending on duty_ns
+ *   /duty_ns
+ *      * always readable
+ *      * write with desired duty portion in nanoseconds
+ *      * may return with error depending on period_ns
+ *   /run
+ *      * always readable
+ *      * write with "1" to start generating pwm signal, "0" to stop it
+ */
+static ssize_t pwm_polarity_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	const struct pwm_device *pwm = dev_get_drvdata(dev);
+	ssize_t	status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(PWMF_EXPORT, &pwm->flags))
+		status = -EIO;
+	else
+		status = sprintf(buf, "%d\n", pwm->polarity);
+
+	mutex_unlock(&sysfs_lock);
+
+	return status;
+}
+
+static ssize_t pwm_polarity_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct pwm_device *pwm = dev_get_drvdata(dev);
+	ssize_t status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(PWMF_EXPORT, &pwm->flags))
+		status = -EIO;
+	else {
+		long value;
+
+		status = kstrtol(buf, 0, &value);
+		if (status == 0) {
+			if (value == 0) {
+				if (pwm->polarity == PWM_POLARITY_NORMAL)
+					goto fail_unlock;
+				status = pwm_set_polarity(pwm,
+							PWM_POLARITY_NORMAL);
+			} else {
+				if (pwm->polarity == PWM_POLARITY_INVERSED)
+					goto fail_unlock;
+				status = pwm_set_polarity(pwm,
+							PWM_POLARITY_INVERSED);
+			}
+		}
+	}
+
+fail_unlock:
+	mutex_unlock(&sysfs_lock);
+	return status ? : size;
+}
+
+static const DEVICE_ATTR(polarity, 0644,
+		pwm_polarity_show, pwm_polarity_store);
+
+
+static ssize_t pwm_period_ns_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	const struct pwm_device *pwm = dev_get_drvdata(dev);
+	ssize_t	status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(PWMF_EXPORT, &pwm->flags))
+		status = -EIO;
+	else
+		status = sprintf(buf, "%d\n", pwm->period);
+
+	mutex_unlock(&sysfs_lock);
+
+	return status;
+}
+
+static ssize_t pwm_period_ns_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct pwm_device *pwm = dev_get_drvdata(dev);
+	ssize_t status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(PWMF_EXPORT, &pwm->flags))
+		status = -EIO;
+	else {
+		long value;
+
+		status = kstrtol(buf, 0, &value);
+		if (status == 0) {
+			if (pwm->duty < 0)
+				pwm->period = value;
+			else
+				status = pwm_config(pwm, pwm->duty, value);
+		}
+	}
+
+	mutex_unlock(&sysfs_lock);
+
+	return status ? : size;
+}
+
+static ssize_t pwm_duty_ns_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	const struct pwm_device *pwm = dev_get_drvdata(dev);
+	ssize_t	status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(PWMF_EXPORT, &pwm->flags))
+		status = -EIO;
+	else
+		status = sprintf(buf, "%d\n", pwm->duty);
+
+	mutex_unlock(&sysfs_lock);
+
+	return status;
+}
+
+static ssize_t pwm_duty_ns_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct pwm_device *pwm = dev_get_drvdata(dev);
+	ssize_t status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(PWMF_EXPORT, &pwm->flags))
+		status = -EIO;
+	else {
+		long value;
+
+		status = kstrtol(buf, 0, &value);
+		if (status == 0) {
+			if (pwm->period <= 0)
+				pwm->duty = value;
+			else
+				status = pwm_config(pwm, value, pwm->period);
+		}
+	}
+
+	mutex_unlock(&sysfs_lock);
+
+	return status ? : size;
+}
+
+static ssize_t pwm_run_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	const struct pwm_device *pwm = dev_get_drvdata(dev);
+	ssize_t	status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(PWMF_EXPORT, &pwm->flags))
+		status = -EIO;
+	else
+		status = sprintf(buf, "%d\n",
+				!!test_bit(PWMF_ENABLED, &pwm->flags));
+
+	mutex_unlock(&sysfs_lock);
+
+	return status;
+}
+
+static ssize_t pwm_run_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct pwm_device *pwm = dev_get_drvdata(dev);
+	ssize_t	status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(PWMF_EXPORT, &pwm->flags))
+		status = -EIO;
+	else {
+		long		value;
+
+		status = kstrtol(buf, 0, &value);
+		if (status == 0) {
+			if (value)
+				status = pwm_enable(pwm);
+			else
+				pwm_disable(pwm);
+		}
+	}
+
+	mutex_unlock(&sysfs_lock);
+
+	return status ? : size;
+}
+
+static struct device_attribute pwm_dev_attrs[] = {
+	__ATTR(period_ns, 0644, pwm_period_ns_show, pwm_period_ns_store),
+	__ATTR(duty_ns, 0644, pwm_duty_ns_show, pwm_duty_ns_store),
+	__ATTR(run, 0644, pwm_run_show, pwm_run_store),
+	__ATTR_NULL,
+};
+
+/*
+ * /sys/class/pwm/pwmchipN/
+ *   /base ... matching pwm_chip.base (N)
+ *   /ngpio ... matching pwm_chip.npwm
+ */
+
+static ssize_t chip_base_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	const struct pwm_chip	*chip = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", chip->base);
+}
+
+static ssize_t chip_npwm_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	const struct pwm_chip	*chip = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", chip->npwm);
+}
+
+static int pwm_export(struct pwm_device *pwm)
+{
+	struct device *dev;
+	int status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(PWMF_REQUESTED, &pwm->flags) ||
+		test_bit(PWMF_EXPORT, &pwm->flags)) {
+		pr_debug("pwm %d unavailable (requested=%d, exported=%d)\n",
+			pwm->pwm,
+			test_bit(PWMF_REQUESTED, &pwm->flags),
+			test_bit(PWMF_EXPORT, &pwm->flags));
+
+		status = -EPERM;
+		goto fail_unlock;
+	}
+
+	pwm_class.class_attrs = NULL;
+	pwm_class.dev_attrs = pwm_dev_attrs;
+	dev = device_create(&pwm_class, pwm->chip->dev, MKDEV(0, 0),
+			pwm, "pwm%u", pwm->pwm);
+	if (IS_ERR(dev)) {
+		status = PTR_ERR(dev);
+		goto fail_unlock;
+	}
+
+	if (pwm->chip->ops->set_polarity) {
+		status = device_create_file(dev, &dev_attr_polarity);
+		if (status)
+			goto fail_unregister_device;
+	}
+
+	set_bit(PWMF_EXPORT, &pwm->flags);
+	mutex_unlock(&sysfs_lock);
+	return 0;
+
+fail_unregister_device:
+	device_unregister(dev);
+fail_unlock:
+	mutex_unlock(&sysfs_lock);
+	return status;
+}
+
+static int match_export(struct device *dev, void *data)
+{
+	return dev_get_drvdata(dev) == data;
+}
+
+/*
+ * /sys/class/pwm/export ... write-only
+ *	integer N ... number of pwm to export (full access)
+ * /sys/class/pwm/unexport ... write-only
+ *	integer N ... number of pwm to unexport
+ */
+static ssize_t export_store(struct class *class,
+				struct class_attribute *attr,
+				const char *buf, size_t len)
+{
+	long pwm;
+	int status;
+	struct pwm_device *dev;
+	struct pwm_chip *chip;
+
+	status = kstrtol(buf, 0, &pwm);
+	if (status < 0)
+		goto done;
+
+	if (!pwm_is_valid(pwm) || !pwm_table[pwm]) {
+		status = -ENODEV;
+		goto done;
+	}
+	chip = pwm_table[pwm]->chip;
+	if (!chip) {
+		status = -ENODEV;
+		goto done;
+	}
+	dev = pwm_request_from_chip(chip, pwm - chip->base, "sysfs");
+	if (IS_ERR(dev)) {
+		status = -ENODEV;
+		goto done;
+	}
+	status = pwm_export(dev);
+	if (status < 0)
+		pwm_free(dev);
+done:
+	if (status)
+		pr_debug("%s: status %d\n", __func__, status);
+	return status ? : len;
+}
+
+static ssize_t unexport_store(struct class *class,
+				struct class_attribute *attr,
+				const char *buf, size_t len)
+{
+	long pwm;
+	int status;
+	struct pwm_device *dev;
+	struct device *d;
+
+	status = kstrtol(buf, 0, &pwm);
+	if (status < 0)
+		goto done;
+
+	status = -EINVAL;
+
+	/* reject bogus pwms */
+	if (!pwm_is_valid(pwm))
+		goto done;
+
+	dev = pwm_table[pwm];
+	if (dev && test_and_clear_bit(PWMF_EXPORT, &dev->flags)) {
+		d = class_find_device(&pwm_class, NULL, dev, match_export);
+		if (d)
+			device_unregister(d);
+		status = 0;
+		pwm_put(dev);
+	}
+done:
+	if (status)
+		pr_debug("%s: status %d\n", __func__, status);
+	return status ? : len;
+}
+
+static struct class_attribute pwmchip_class_attrs[] = {
+	__ATTR(export, 0200, NULL, export_store),
+	__ATTR(unexport, 0200, NULL, unexport_store),
+	__ATTR_NULL,
+};
+
+static struct device_attribute pwmchip_dev_attrs[] = {
+	__ATTR(base, 0444, chip_base_show, NULL),
+	__ATTR(npwm, 0444, chip_npwm_show, NULL),
+	__ATTR_NULL,
+};
+
+static struct class pwm_class = {
+	.name =		"pwm",
+	.owner =	THIS_MODULE,
+	.class_attrs =	pwmchip_class_attrs,
+	.dev_attrs =	pwmchip_dev_attrs,
+};
+
+static int pwmchip_export(struct pwm_chip *chip)
+{
+	struct device *dev;
+
+	mutex_lock(&sysfs_lock);
+	pwm_class.class_attrs = pwmchip_class_attrs;
+	pwm_class.dev_attrs = pwmchip_dev_attrs;
+	dev = device_create(&pwm_class, chip->dev, MKDEV(0, 0), chip,
+				"pwmchip%d", chip->base);
+
+	chip->exported = (!IS_ERR(dev));
+	mutex_unlock(&sysfs_lock);
+
+	if (chip->exported)
+		return 0;
+
+	return PTR_ERR(dev);
+}
+
+static void pwmchip_unexport(struct pwm_chip *chip)
+{
+	int status, i;
+	struct device *dev;
+
+	mutex_lock(&sysfs_lock);
+	dev = class_find_device(&pwm_class, NULL, chip, match_export);
+	if (dev) {
+		put_device(dev);
+		device_unregister(dev);
+		for (i = chip->base; i < chip->base + chip->npwm; i++)
+			pwm_table[i] = NULL;
+		chip->exported = 0;
+		status = 0;
+	} else
+		status = -ENODEV;
+	mutex_unlock(&sysfs_lock);
+
+	if (status)
+		pr_debug("%s: pwm chip status %d\n", __func__, status);
+}
+
+static int __init pwmlib_sysfs_init(void)
+{
+	int status;
+
+	status = class_register(&pwm_class);
+
+	return status;
+}
+postcore_initcall(pwmlib_sysfs_init);
+
+#else
+static inline int pwmchip_export(struct pwm_chip *chip)
+{
+	return 0;
+}
+
+static inline void pwmchip_unexport(struct pwm_chip *chip)
+{
+}
+
+#endif /* CONFIG_PWM_SYSFS */
+
+
 static struct pwm_device *pwm_to_device(unsigned int pwm)
 {
 	return radix_tree_lookup(&pwm_tree, pwm);
@@ -77,8 +534,10 @@ static void free_pwms(struct pwm_chip *chip)
 	for (i = 0; i < chip->npwm; i++) {
 		struct pwm_device *pwm = &chip->pwms[i];
 		radix_tree_delete(&pwm_tree, pwm->pwm);
+#ifdef CONFIG_PWM_SYSFS
+		pwm_table[i + chip->base]->chip = NULL;
+#endif
 	}
-
 	bitmap_clear(allocated_pwms, chip->base, chip->npwm);
 
 	kfree(chip->pwms);
@@ -258,6 +717,9 @@ int pwmchip_add(struct pwm_chip *chip)
 		pwm->chip = chip;
 		pwm->pwm = chip->base + i;
 		pwm->hwpwm = i;
+#ifdef CONFIG_PWM_SYSFS
+		pwm_table[i + chip->base] = pwm;
+#endif
 
 		radix_tree_insert(&pwm_tree, pwm->pwm, pwm);
 	}
@@ -272,6 +734,8 @@ int pwmchip_add(struct pwm_chip *chip)
 	if (IS_ENABLED(CONFIG_OF))
 		of_pwmchip_add(chip);
 
+	ret = pwmchip_export(chip);
+
 out:
 	mutex_unlock(&pwm_lock);
 	return ret;
@@ -307,6 +771,7 @@ int pwmchip_remove(struct pwm_chip *chip)
 		of_pwmchip_remove(chip);
 
 	free_pwms(chip);
+	pwmchip_unexport(chip);
 
 out:
 	mutex_unlock(&pwm_lock);
@@ -400,10 +865,19 @@ EXPORT_SYMBOL_GPL(pwm_free);
  */
 int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
 {
+	int status;
+
 	if (!pwm || duty_ns < 0 || period_ns <= 0 || duty_ns > period_ns)
 		return -EINVAL;
 
-	return pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns);
+	status = pwm->chip->ops->config(pwm->chip, pwm, duty_ns, period_ns);
+#ifdef CONFIG_PWM_SYSFS
+	if (status == 0) {
+		pwm->period = period_ns;
+		pwm->duty = duty_ns;
+	}
+#endif
+	return status;
 }
 EXPORT_SYMBOL_GPL(pwm_config);
 
@@ -416,6 +890,8 @@ EXPORT_SYMBOL_GPL(pwm_config);
  */
 int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
 {
+	int status;
+
 	if (!pwm || !pwm->chip->ops)
 		return -EINVAL;
 
@@ -425,7 +901,12 @@ int pwm_set_polarity(struct pwm_device *pwm, enum pwm_polarity polarity)
 	if (test_bit(PWMF_ENABLED, &pwm->flags))
 		return -EBUSY;
 
-	return pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity);
+	status = pwm->chip->ops->set_polarity(pwm->chip, pwm, polarity);
+#ifdef CONFIG_PWM_SYSFS
+	if (!status)
+		pwm->polarity = polarity;
+#endif
+	return status;
 }
 EXPORT_SYMBOL_GPL(pwm_set_polarity);
 
@@ -486,7 +967,7 @@ static struct pwm_chip *of_node_to_pwmchip(struct device_node *np)
  * becomes mandatory for devices that look up the PWM device via the con_id
  * parameter.
  */
-static struct pwm_device *of_pwm_request(struct device_node *np,
+struct pwm_device *of_pwm_request(struct device_node *np,
 					 const char *con_id)
 {
 	struct pwm_device *pwm = NULL;
@@ -495,6 +976,9 @@ static struct pwm_device *of_pwm_request(struct device_node *np,
 	int index = 0;
 	int err;
 
+	if (!np)
+		return ERR_PTR(-ENODEV);
+
 	if (con_id) {
 		index = of_property_match_string(np, "pwm-names", con_id);
 		if (index < 0)
@@ -545,6 +1029,7 @@ put:
 
 	return pwm;
 }
+EXPORT_SYMBOL(of_pwm_request);
 
 /**
  * pwm_add_table() - register PWM device consumers
@@ -749,6 +1234,9 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
 		if (test_bit(PWMF_ENABLED, &pwm->flags))
 			seq_printf(s, " enabled");
 
+		if (test_bit(PWMF_EXPORT, &pwm->flags))
+			seq_printf(s, " sysfs_exported");
+
 		seq_printf(s, "\n");
 	}
 }
diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c
new file mode 100644
index 0000000..fe504ab
--- /dev/null
+++ b/drivers/pwm/pwm-pca9685.c
@@ -0,0 +1,171 @@
+/* drivers/pwm/pwm-pca9685.c
+ * 
+ * Copyright (C) 2013 Koen Kooi
+ * 
+ * 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 is will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABLILITY of FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Genernal Public License for more details.
+ *
+ */
+
+
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/pwm.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+
+
+#define PCA9685_REG_PSC			0xFE
+#define PCA9685_REG_LED_ON(led)		0x6 + (led >> 2)
+#define PCA9685_REG_LED_OFF(led)	0x7 + (led >> 2)
+
+#define NUM_PWM_CHANNEL			16	/* PCA9685 channels */
+
+struct pca9685_pwm_chip {
+	struct pwm_chip chip;
+	unsigned long period_cycles[NUM_PWM_CHANNEL];
+	enum pwm_polarity polarity[NUM_PWM_CHANNEL];
+};
+
+struct pca9685_device {
+	struct i2c_client *client;
+	/* TODO */
+};
+
+static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+		int duty_ns, int period_ns)
+{
+	pr_info("PWM config");
+	return 0;
+}
+
+static int pca9685_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
+		enum pwm_polarity polarity)
+{
+	pr_info("PWM set polarity");
+	return 0;
+}
+
+static int pca9685_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	pr_info("PWM enable");
+	return 0;
+}
+
+static void pca9685_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	pr_info("PWM disable");
+}
+
+static void pca9685_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	pr_info("PWM free");
+	if (test_bit(PWMF_ENABLED, &pwm->flags)) {
+		dev_warn(chip->dev, "Removing PWM device without disabling\n");
+	}
+}
+
+static const struct pwm_ops pca9685_pwm_ops = {
+	.free		= pca9685_pwm_free,
+	.config		= pca9685_pwm_config,
+	.set_polarity	= pca9685_pwm_set_polarity,
+	.enable		= pca9685_pwm_enable,
+	.disable	= pca9685_pwm_disable,
+	.owner		= THIS_MODULE,
+};
+
+/* TODO */
+
+static int pca9685_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct pca9685_device *dev;
+	struct pca9685_pwm_chip *pc;
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter,
+		I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+		I2C_FUNC_SMBUS_I2C_BLOCK)) {
+		printk(KERN_ERR "%s: needed i2c functionality is not supported\n", __func__);
+		return -ENODEV;
+	}
+	
+	dev = kzalloc(sizeof(struct pca9685_device), GFP_KERNEL);
+	if (dev == NULL) {
+		printk(KERN_ERR "%s: no memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	dev->client = client;
+	i2c_set_clientdata(client, dev);
+
+	pc = kzalloc(sizeof(struct pca9685_pwm_chip), GFP_KERNEL);
+	if (pc == NULL) {
+		printk(KERN_ERR "%s: no memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	pc->chip.dev = &client->dev;
+	pc->chip.ops = &pca9685_pwm_ops;
+	pc->chip.base = -1;
+        pc->chip.npwm = 16;
+
+	ret = pwmchip_add(&pc->chip);
+	if (ret < 0) {
+	pr_err("pwm-pca9685: pwmchip_add() failed: %d\n", ret);
+		return ret;
+        }
+
+	return 0;
+}
+
+static int pca9685_remove(struct i2c_client *client)
+{
+	struct pca9685_client *dev = i2c_get_clientdata(client);
+
+	/* TODO: do something */
+
+	kfree(dev);
+	return 0;
+}
+
+static const struct i2c_device_id pca9685_id[] = {
+	{ "pwm-pca9685", 0 },
+	{ }
+};
+
+static struct i2c_driver pca9685_driver = {
+	.probe    = pca9685_probe,
+	.remove   = pca9685_remove,
+	.id_table = pca9685_id,
+	.driver   = {
+		.name = "pca9685",
+	},
+};
+
+static int __init pca9685_init_driver(void)
+{
+	return i2c_add_driver(&pca9685_driver);
+}
+
+static void __exit pca9685_exit_driver(void)
+{
+	i2c_del_driver(&pca9685_driver);
+}
+
+module_init(pca9685_init_driver);
+module_exit(pca9685_exit_driver);
+
+MODULE_AUTHOR("Koen Kooi <koen@dominion.thruhere.net>");
+MODULE_DESCRIPTION("PCA9685 I2C 16 channel PWM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index 72a6dd4..af6f162 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -341,7 +341,7 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 	configure_polarity(pc, pwm->hwpwm);
 
 	/* Enable TBCLK before enabling PWM device */
-	clk_enable(pc->tbclk);
+	clk_prepare_enable(pc->tbclk);
 
 	/* Enable time counter for free_run */
 	ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
@@ -372,7 +372,7 @@ 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);
+	clk_disable_unprepare(pc->tbclk);
 
 	/* Stop Time base counter */
 	ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT);
diff --git a/drivers/pwm/pwm_test.c b/drivers/pwm/pwm_test.c
new file mode 100644
index 0000000..9c07880
--- /dev/null
+++ b/drivers/pwm/pwm_test.c
@@ -0,0 +1,341 @@
+/*
+ * PWM Test driver
+ *
+ * Copyright (C) 2012 Texas 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
+
+struct pwm_test {
+	struct pwm_device *pwm;
+	struct class *pwm_test_class;
+	int period;
+	int duty;
+	enum pwm_polarity polarity;
+	int run;
+};
+
+static ssize_t pwm_test_show_duty(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct pwm_test *pwm_test = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", pwm_test->duty);
+}
+
+static ssize_t pwm_test_store_duty(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int rc;
+	struct pwm_test *pwm_test = dev_get_drvdata(dev);
+	int duty;
+
+	rc = kstrtoint(buf, 0, &duty);
+	if (rc)
+		return rc;
+
+	if (duty < 0)
+		return -EINVAL;
+
+	rc = pwm_config(pwm_test->pwm, duty, pwm_test->period);
+	if (rc) {
+		dev_err(dev, "pwm_config() failed\n");
+		return rc;
+	}
+
+	pwm_test->duty = duty;
+
+	return count;
+}
+
+static ssize_t pwm_test_show_period(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct pwm_test *pwm_test = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", pwm_test->period);
+}
+
+static ssize_t pwm_test_store_period(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int rc;
+	struct pwm_test *pwm_test = dev_get_drvdata(dev);
+	int period;
+
+	rc = kstrtoint(buf, 0, &period);
+	if (rc)
+		return rc;
+
+	if (period < 0)
+		return -EINVAL;
+
+	/* same period? just return */
+	if (pwm_test->period == period)
+		return count;
+
+	rc = pwm_config(pwm_test->pwm, pwm_test->duty, period);
+	if (rc) {
+		dev_err(dev, "pwm_config() failed\n");
+		return rc;
+	}
+
+	pwm_test->period = period;
+
+	return count;
+}
+
+static ssize_t pwm_test_show_run(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct pwm_test *pwm_test = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", pwm_test->run);
+}
+
+static ssize_t pwm_test_store_run(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int rc;
+	struct pwm_test *pwm_test = dev_get_drvdata(dev);
+	int run;
+
+	rc = kstrtoint(buf, 0, &run);
+	if (rc)
+		return rc;
+
+	/* only 0 & 1 allowed */
+	if (run != 0 && run != 1)
+		return -EINVAL;
+
+	/* same state, don't bother */
+	if (run == pwm_test->run)
+		return count;
+
+	if (run) {
+		rc = pwm_enable(pwm_test->pwm);
+		if (rc != 0) {
+			dev_err(dev, "pwm_enable failed\n");
+			return rc;
+		}
+	} else
+		pwm_disable(pwm_test->pwm);
+
+	pwm_test->run = run;
+
+	return count;
+}
+
+static ssize_t pwm_test_show_polarity(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct pwm_test *pwm_test = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", pwm_test->polarity);
+}
+
+static ssize_t pwm_test_store_polarity(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int rc;
+	struct pwm_test *pwm_test = dev_get_drvdata(dev);
+	int val;
+	enum pwm_polarity polarity;
+
+	rc = kstrtoint(buf, 0, &val);
+	if (rc)
+		return rc;
+
+	/* only zero and one allowed */
+	if (val != 0 && val != 1)
+		return -EINVAL;
+
+	polarity = val ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL;
+
+	/* same? don't do anything */
+	if (polarity == pwm_test->polarity)
+		return count;
+
+	/* polarity can only change when we stop the pwm */
+	if (pwm_test->run)
+		pwm_disable(pwm_test->pwm);
+
+	rc = pwm_set_polarity(pwm_test->pwm, polarity);
+	if (rc) {
+		dev_err(dev, "pwm_set_polarity failed\n");
+		if (pwm_test->run)
+			pwm_enable(pwm_test->pwm);
+		return rc;
+	}
+
+	if (pwm_test->run)
+		pwm_enable(pwm_test->pwm);
+
+	pwm_test->polarity = polarity;
+
+	return count;
+}
+
+static DEVICE_ATTR(duty, S_IRUSR | S_IWUSR, pwm_test_show_duty, pwm_test_store_duty);
+static DEVICE_ATTR(period, S_IRUSR | S_IWUSR, pwm_test_show_period, pwm_test_store_period);
+static DEVICE_ATTR(polarity, S_IRUSR | S_IWUSR, pwm_test_show_polarity,
+		pwm_test_store_polarity);
+static DEVICE_ATTR(run, S_IRUSR | S_IWUSR , pwm_test_show_run, pwm_test_store_run);
+
+static const struct attribute *pwm_attrs[] = {
+	&dev_attr_duty.attr,
+	&dev_attr_period.attr,
+	&dev_attr_run.attr,
+	&dev_attr_polarity.attr,
+	NULL,
+};
+
+static const struct attribute_group pwm_device_attr_group = {
+	.attrs = (struct attribute **) pwm_attrs,
+};
+
+static int pwm_test_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct pwm_test *pwm_test;
+	struct of_phandle_args args;
+	struct pinctrl *pinctrl;
+	u32 val;
+	int rc;
+
+	if (node == NULL) {
+		dev_err(dev, "Non DT platforms not supported\n");
+		return -EINVAL;
+	}
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev, "Unable to select pin group\n");
+
+	pwm_test = devm_kzalloc(&pdev->dev, sizeof(*pwm_test), GFP_KERNEL);
+	if (!pwm_test) {
+		dev_err(&pdev->dev, "memory error\n");
+		return -ENOMEM;
+	}
+	platform_set_drvdata(pdev, pwm_test);
+
+	/* now do the probe time config */
+	pwm_test->pwm = devm_pwm_get(&pdev->dev, NULL);
+	if (IS_ERR(pwm_test->pwm)) {
+		dev_err(dev, "unable to request PWM\n");
+		return PTR_ERR(pwm_test->pwm);
+	}
+
+	rc = of_parse_phandle_with_args(node, "pwms", "#pwm-cells", 0, &args);
+	if (rc != 0) {
+		dev_err(dev, "of_parse_phandle_with_args() failed\n");
+		return rc;
+	}
+
+	/* read the period */
+	pwm_test->period = args.args[1];
+
+	/* should be at least 2, but 3 is possible to store polarity */
+	pwm_test->polarity = PWM_POLARITY_NORMAL;
+	/* PWM_SPEC_POLARITY is (1 << 0) */
+	if (args.args_count >= 3 && (args.args[2] & (1 << 0)) != 0)
+		pwm_test->polarity = PWM_POLARITY_INVERSED;
+
+	/* Determine the duty from the device tree */
+	rc = of_property_read_u32(node, "duty", &val);
+	if (rc != 0)
+		val = 0;	/* default is 0 */
+	pwm_test->duty = val;
+
+	/* polarity is already set */
+	rc = pwm_config(pwm_test->pwm, pwm_test->duty, pwm_test->period);
+	if (rc) {
+		dev_err(dev, "pwm_config() failed\n");
+		return rc;
+	}
+
+	/* Determine running or not from the device tree */
+	rc = of_property_read_u32(node, "enabled", &val);
+	if (rc < 0)
+		val = 0;	/* default is disabled */
+
+	/* single bit */
+	pwm_test->run = !!val;
+
+	if (pwm_test->run) {
+		rc = pwm_enable(pwm_test->pwm);
+		if (rc < 0) {
+			dev_err(dev, "pwm_enable failed\n");
+			return rc;
+		}
+	}
+
+	rc = sysfs_create_group(&dev->kobj, &pwm_device_attr_group);
+	if (rc != 0) {
+		dev_err(dev, "Unable to create sysfs entries\n");
+		return rc;
+	}
+
+	return 0;
+}
+
+static int pwm_test_remove(struct platform_device *pdev)
+{
+	struct pwm_test *pwm_test = platform_get_drvdata(pdev);
+
+	sysfs_remove_group(&pdev->dev.kobj, &pwm_device_attr_group);
+
+	if (pwm_test->run) {
+		pwm_config(pwm_test->pwm, 0, 0x1000);
+		pwm_disable(pwm_test->pwm);
+	}
+
+	devm_pwm_put(&pdev->dev, pwm_test->pwm);
+	return 0;
+}
+
+static struct of_device_id pwm_test_of_match[] = {
+	{ .compatible = "pwm_test" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, pwm_test_of_match);
+
+static struct platform_driver pwm_test_driver = {
+	.driver		= {
+		.name		= "pwm_test",
+		.owner		= THIS_MODULE,
+		.of_match_table	= of_match_ptr(pwm_test_of_match),
+	},
+	.probe		= pwm_test_probe,
+	.remove		= pwm_test_remove,
+};
+
+module_platform_driver(pwm_test_driver);
+
+MODULE_DESCRIPTION("pwm_test Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pwm_test");
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 5a0f54a..b160fcc 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2294,6 +2294,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
 {
 	struct regulator_dev *rdev = regulator->rdev;
 	int ret = 0;
+	int old_min_uV, old_max_uV;
 
 	mutex_lock(&rdev->mutex);
 
@@ -2315,18 +2316,29 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
 	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
 	if (ret < 0)
 		goto out;
+
+	/* restore original values in case of error */
+	old_min_uV = regulator->min_uV;
+	old_max_uV = regulator->max_uV;
 	regulator->min_uV = min_uV;
 	regulator->max_uV = max_uV;
 
 	ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
 	if (ret < 0)
-		goto out;
+		goto out2;
 
 	ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
+	if (ret < 0)
+		goto out2;
 
 out:
 	mutex_unlock(&rdev->mutex);
 	return ret;
+out2:
+	regulator->min_uV = old_min_uV;
+	regulator->max_uV = old_max_uV;
+	mutex_unlock(&rdev->mutex);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_set_voltage);
 
@@ -3774,6 +3786,7 @@ static int __init regulator_init_complete(void)
 	struct regulation_constraints *c;
 	int enabled, ret;
 
+#ifndef CONFIG_REGULATOR_DUMMY
 	/*
 	 * Since DT doesn't provide an idiomatic mechanism for
 	 * enabling full constraints and since it's much more natural
@@ -3782,6 +3795,7 @@ static int __init regulator_init_complete(void)
 	 */
 	if (of_have_populated_dt())
 		has_full_constraints = true;
+#endif
 
 	mutex_lock(&regulator_list_mutex);
 
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index a936efb..690097b 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -41,4 +41,15 @@ config STE_MODEM_RPROC
 	  This can be either built-in or a loadable module.
 	  If unsure say N.
 
+config PRU_RPROC
+	tristate "AM33xx PRU remoteproc support"
+	depends on EXPERIMENTAL
+	depends on HAS_DMA && SOC_AM33XX
+	select REMOTEPROC
+	default n
+	help
+	  Say y or m here to support AM33xx PRU
+	  This can be either built-in or a loadable module.
+	  If unsure say N.
+
 endmenu
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 391b651..9042660 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -9,3 +9,4 @@ remoteproc-y				+= remoteproc_virtio.o
 remoteproc-y				+= remoteproc_elf_loader.o
 obj-$(CONFIG_OMAP_REMOTEPROC)		+= omap_remoteproc.o
 obj-$(CONFIG_STE_MODEM_RPROC)	 	+= ste_modem_rproc.o
+obj-$(CONFIG_PRU_RPROC)		 	+= pru_rproc.o
diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
new file mode 100644
index 0000000..113ad80
--- /dev/null
+++ b/drivers/remoteproc/pru_rproc.c
@@ -0,0 +1,240 @@
+/*
+ * PRU driver for TI's AM33xx series of SoCs
+ * 
+ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.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/module.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/remoteproc.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/genalloc.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/io.h>
+
+#include "remoteproc_internal.h"
+
+/* PRU control structure */
+struct pruproc {
+	struct rproc *rproc;
+	struct platform_device *pdev;
+	struct resource_table *table;
+	void __iomem *vaddr;
+	dma_addr_t paddr;
+};
+
+/* Loads the firmware to shared memory. */
+static int pruproc_load_segments(struct rproc *rproc, const struct firmware *fw)
+{
+	struct pruproc *pruproc = rproc->priv;
+
+	dev_dbg(&pruproc->pdev->dev, "%s\n", __func__);
+
+	return 0;
+}
+
+/* Find the resource table inside the remote processor's firmware. */
+static struct resource_table *
+pruproc_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
+		     int *tablesz)
+{
+	struct pruproc *pruproc = rproc->priv;
+	struct resource_table *table;
+
+	table = devm_kzalloc(&pruproc->pdev->dev, sizeof(*table), GFP_KERNEL);
+
+	dev_dbg(&pruproc->pdev->dev, "%s\n", __func__);
+
+	return table;
+}
+
+static int pruproc_sanity_check(struct rproc *rproc, const struct firmware *fw)
+{
+	return 0;
+}
+
+/* PRU firmware handler operations */
+const struct rproc_fw_ops pruproc_fw_ops = {
+	.find_rsc_table	= pruproc_find_rsc_table,
+	.load		= pruproc_load_segments,
+	.sanity_check	= pruproc_sanity_check,
+};
+
+/* Kick the modem with specified notification id */
+static void pruproc_kick(struct rproc *rproc, int vqid)
+{
+	struct pruproc *pruproc = rproc->priv;
+
+	dev_dbg(&pruproc->pdev->dev, "kick vqid:%d\n", vqid);
+}
+
+/* Start the PRU modem */
+static int pruproc_start(struct rproc *rproc)
+{
+	struct pruproc *pruproc = rproc->priv;
+
+	dev_dbg(&pruproc->pdev->dev, "start pru\n");
+
+	return 0;
+}
+
+/* Stop the PRU modem */
+static int pruproc_stop(struct rproc *rproc)
+{
+	struct pruproc *pruproc = rproc->priv;
+
+	dev_dbg(&pruproc->pdev->dev, "stop PRU\n");
+
+	return 0;
+}
+
+static struct rproc_ops pruproc_ops = {
+	.start		= pruproc_start,
+	.stop		= pruproc_stop,
+	.kick		= pruproc_kick,
+};
+
+/* PRU is unregistered */
+static int pruproc_remove(struct platform_device *pdev)
+{
+	struct pruproc *pruproc = platform_get_drvdata(pdev);
+
+	dev_dbg(&pdev->dev, "remove pru\n");
+
+	/* Unregister as remoteproc device */
+	rproc_del(pruproc->rproc);
+	rproc_put(pruproc->rproc);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+/* Handle probe of a modem device */
+static int pruproc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct pruproc *pruproc;
+	struct rproc *rproc;
+	struct resource *res;
+	struct pinctrl *pinctrl;
+	int err;
+
+	dev_dbg(dev, "probe pru\n");
+
+	/* get pinctrl */
+	pinctrl = devm_pinctrl_get_select_default(dev);
+	if (IS_ERR(pinctrl)) {
+		err = PTR_ERR(pinctrl);
+		/* deferring probe */
+		if (err == -EPROBE_DEFER) {
+			dev_warn(dev, "deferring proble\n");
+			return err;
+		}
+		dev_warn(dev, "pins are not configured from the driver\n");
+	}
+
+	/* we only work on OF */
+	if (dev->of_node == NULL) {
+		dev_err(dev, "Only OF configuration supported\n");
+		err = -ENODEV;
+		goto fail_of_node;
+	}
+
+	pm_runtime_enable(dev);
+	err = pm_runtime_get_sync(dev);
+	if (err != 0) {
+		dev_err(dev, "pm_runtime_get_sync failed\n");
+		goto fail_pm_runtime_get_sync;
+	}
+
+	err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+	if (err) {
+		dev_err(dev, "dma_set_coherent_mask: %d\n", err);
+		goto fail_dma_set_coherent_mask;
+	}
+
+	rproc = rproc_alloc(dev, pdev->name, &pruproc_ops,
+			"prutest.bin", sizeof(*pruproc));
+	if (!rproc) {
+		dev_err(dev, "rproc_alloc failed\n");
+		err = -ENOMEM;
+		goto fail_rproc_alloc;
+	}
+
+	pruproc = rproc->priv;
+	pruproc->pdev = pdev;
+	pruproc->rproc = rproc;
+
+	platform_set_drvdata(pdev, pruproc);
+
+	/* Set the PRU specific firmware handler */
+	rproc->fw_ops = &pruproc_fw_ops;
+
+	/* Register as a remoteproc device */
+	err = rproc_add(rproc);
+	if (err) {
+		dev_err(dev, "rproc_add failed\n");
+		goto fail_rproc_add;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(dev, "failed to parse MEM resource\n");
+		goto fail_platform_get_resource;
+	}
+
+	pruproc->vaddr = devm_ioremap(dev, res->start, resource_size(res));
+	if (pruproc->vaddr == NULL) {
+		dev_err(dev, "failed to parse MEM resource\n");
+		goto fail_devm_ioremap;
+	}
+
+	dev_info(dev, "Loaded OK\n");
+
+	return 0;
+fail_devm_ioremap:
+fail_platform_get_resource:
+	rproc_del(rproc);
+fail_rproc_add:
+	platform_set_drvdata(pdev, NULL);
+	rproc_put(rproc);
+fail_rproc_alloc:
+fail_dma_set_coherent_mask:
+fail_of_node:
+	pm_runtime_disable(dev);
+fail_pm_runtime_get_sync:
+	return err;
+}
+
+static const struct of_device_id pru_rproc_dt_ids[] = {
+	{ .compatible = "ti,pru-rproc", .data = NULL, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pruss_dt_ids);
+
+static struct platform_driver pruproc_driver = {
+	.driver	= {
+		.name	= "pru-rproc",
+		.owner	= THIS_MODULE,
+		.of_match_table = pru_rproc_dt_ids,
+	},
+	.probe	= pruproc_probe,
+	.remove	= pruproc_remove,
+};
+
+module_platform_driver(pruproc_driver);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PRU Remote Processor control driver");
+MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
diff --git a/drivers/rstctl/Kconfig b/drivers/rstctl/Kconfig
new file mode 100644
index 0000000..b943253
--- /dev/null
+++ b/drivers/rstctl/Kconfig
@@ -0,0 +1,30 @@
+#
+# RSTCTL infrastructure and drivers
+#
+
+menuconfig RSTCTL
+	bool "Reset control subsystem"
+	help
+	  Select this to enable the reset control subsystem
+
+if RSTCTL
+
+config RSTCTL_GPIO
+	tristate "GPIO reset driver"
+	depends on RSTCTL
+	help
+	  This selects the GPIO based reset driver
+
+config RSTCTL_TEST
+	tristate "Test reset driver"
+	depends on RSTCTL
+	help
+	  This selects the test reset driver
+
+config RSTCTL_TEST_CONSUMER
+	tristate "Test reset consumer driver"
+	depends on RSTCTL
+	help
+	  This select the test reset consumer driver
+
+endif
diff --git a/drivers/rstctl/Makefile b/drivers/rstctl/Makefile
new file mode 100644
index 0000000..26dfcf6
--- /dev/null
+++ b/drivers/rstctl/Makefile
@@ -0,0 +1,8 @@
+# rstctl support
+
+ccflags-$(CONFIG_DEBUG_RSTCTL)	+= -DDEBUG
+
+obj-$(CONFIG_RSTCTL)			+= core.o
+obj-$(CONFIG_RSTCTL_TEST)		+= rstctl-test.o
+obj-$(CONFIG_RSTCTL_TEST_CONSUMER)	+= rstctl-test-consumer.o
+obj-$(CONFIG_RSTCTL_GPIO)		+= rstctl-gpio.o
diff --git a/drivers/rstctl/core.c b/drivers/rstctl/core.c
new file mode 100644
index 0000000..a3f02c2
--- /dev/null
+++ b/drivers/rstctl/core.c
@@ -0,0 +1,368 @@
+/*
+ * Core driver for the reset control subsystem
+ *
+ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
+ * Based on bits of rstctl, regulator core, gpio core and clk core
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#define pr_fmt(fmt) "rstctl core: " fmt
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/sysfs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <linux/rstctl.h>
+
+static inline int reset_request(struct rstctl_dev *rdev,
+			const struct rstctl_line *line)
+{
+	/* no request op? */
+	if (rdev->rdesc->ops->request == NULL)
+		return 0;
+
+	return rdev->rdesc->ops->request(rdev, line);
+}
+
+static inline int reset_release(struct rstctl_dev *rdev,
+			const struct rstctl_line *line)
+{
+	/* no release op? */
+	if (rdev->rdesc->ops->release == NULL)
+		return 0;
+
+	return rdev->rdesc->ops->release(rdev, line);
+}
+
+static inline int reset_assert(struct rstctl_dev *rdev,
+			const struct rstctl_line *line)
+{
+	return rdev->rdesc->ops->assert(rdev, line);
+}
+
+static inline int reset_deassert(struct rstctl_dev *rdev,
+			const struct rstctl_line *line)
+{
+	return rdev->rdesc->ops->deassert(rdev, line);
+}
+
+static inline int reset_pulse(struct rstctl_dev *rdev,
+			const struct rstctl_line *line,
+			unsigned long hold_ns)
+{
+	return rdev->rdesc->ops->pulse(rdev, line, hold_ns);
+}
+
+int rstctl_assert(struct rstctl *rctrl)
+{
+	if (IS_ERR_OR_NULL(rctrl))
+		return -EINVAL;
+	return reset_assert(rctrl->rdev, rctrl->line);
+}
+EXPORT_SYMBOL(rstctl_assert);
+
+int rstctl_deassert(struct rstctl *rctrl)
+{
+	if (IS_ERR_OR_NULL(rctrl))
+		return -EINVAL;
+	return reset_deassert(rctrl->rdev, rctrl->line);
+}
+EXPORT_SYMBOL(rstctl_deassert);
+
+int rstctl_pulse(struct rstctl *rctrl, unsigned long hold_ns)
+{
+	if (IS_ERR_OR_NULL(rctrl))
+		return -EINVAL;
+	return reset_pulse(rctrl->rdev, rctrl->line, hold_ns);
+}
+EXPORT_SYMBOL(rstctl_pulse);
+
+/* Mutex taken by all entry points */
+static DEFINE_MUTEX(rstctl_lock);
+
+/* Global list of reset control devices (struct rstctl_dev) */
+static LIST_HEAD(rstctl_dev_list);
+
+static struct rstctl *rstctl_request_line(struct rstctl_dev *rdev,
+		struct device *dev, const struct rstctl_line *line)
+{
+	struct rstctl *rctrl;
+	int index, err;
+
+	index = line - rdev->rdesc->lines;
+
+	/* find if it's already requested */
+	list_for_each_entry(rctrl, &rdev->handles, node) {
+		/* retreive index from the point */
+		if (rctrl->line == line) {
+			dev_err(dev, "Reset %s:%d already requested\n",
+					rdev->rdesc->name, index);
+			return ERR_PTR(-EEXIST);
+		}
+	}
+
+	/* request from the driver */
+	err = reset_request(rdev, line);
+	if (err != 0) {
+		dev_err(dev, "reset_request on %s:%d failed\n",
+				rdev->rdesc->name, index);
+		return ERR_PTR(err);
+	}
+
+	/* allocate */
+	rctrl = kzalloc(sizeof(*rctrl), GFP_KERNEL);
+	if (rctrl == NULL) {
+		dev_err(dev, "Out of memory on %s:%d request\n",
+				rdev->rdesc->name, index);
+		reset_release(rdev, line);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	INIT_LIST_HEAD(&rctrl->node);
+	rctrl->rdev = rdev;
+	rctrl->dev = dev;
+	rctrl->line = line;
+
+	/* add it to the handle list */
+	list_add_tail(&rctrl->node, &rdev->handles);
+
+	return rctrl;
+}
+
+#ifdef CONFIG_OF
+
+static struct rstctl_dev *of_node_to_rstctl_dev(struct device_node *np)
+{
+	struct rstctl_dev *rdev;
+
+	list_for_each_entry(rdev, &rstctl_dev_list, node) {
+		if (rdev->dev && rdev->dev->of_node == np)
+			return rdev;
+	}
+
+	return ERR_PTR(-EPROBE_DEFER);
+}
+
+static struct rstctl *of_rstctl_get(struct device *dev, const char *id)
+{
+	struct device_node *np;
+	struct rstctl *rctrl;
+	struct rstctl_dev *rdev;
+	const struct rstctl_line *line;
+	struct of_phandle_args args;
+	int index, lineidx, err;
+
+	/* sanity check */
+	if (dev == NULL || dev->of_node == NULL)
+		return NULL;
+	np = dev->of_node;
+
+	index = 0;
+	if (id != NULL) {
+		err = of_property_match_string(np, "reset-names", id);
+		if (err < 0) {
+			dev_err(dev, "of_property_match of 'reset-names' failed\n");
+			rctrl = ERR_PTR(err);
+			goto out;
+		}
+		index = err;
+	}
+
+	err = of_parse_phandle_with_args(np, "reset", "#reset-cells", index,
+			&args);
+	if (err != 0) {
+		dev_err(dev, "of_parse_phandle_with_args of 'reset' failed\n");
+		rctrl = ERR_PTR(err);
+		goto out;
+	}
+
+	mutex_lock(&rstctl_lock);
+
+	rdev = of_node_to_rstctl_dev(args.np);
+	if (IS_ERR_OR_NULL(rdev)) {
+		dev_err(dev, "rstctl node not found\n");
+		rctrl = rdev == NULL ? ERR_PTR(-EINVAL) : (void *)rdev;
+		goto out_unlock;
+	}
+
+	if (args.args_count != 2) {
+		dev_err(dev, "#reset-cells not %d\n", 2);
+		rctrl = ERR_PTR(-EINVAL);
+		goto out_unlock;
+	}
+
+	lineidx = args.args[0];
+	/* make sure it's one we handle */
+	if (lineidx < 0 || lineidx >= rdev->rdesc->nlines) {
+		dev_err(dev, "Illegal reset #%d\n", lineidx);
+		rctrl = ERR_PTR(-EINVAL);
+		goto out_unlock;
+	}
+	line = &rdev->rdesc->lines[lineidx];
+
+	rctrl = rstctl_request_line(rdev, dev, line);
+	if (IS_ERR(rctrl)) {
+		dev_err(dev, "rstctl_request_line failed\n");
+		goto out_unlock;
+	}
+
+	/* put the label in */
+	err = of_property_read_string_index(np, "reset-names", index,
+				&rctrl->label);
+	if (err != 0)
+		rctrl->label = np->name;
+
+out_unlock:
+	mutex_unlock(&rstctl_lock);
+out:
+	return rctrl;
+}
+#else
+static inline struct rstctl *of_rstctl_get(struct device *dev,
+		const char *id)
+{
+	return NULL;
+}
+#endif
+
+struct rstctl *rstctl_get(struct device *dev, const char *id)
+{
+	struct rstctl_dev *rdev;
+	struct rstctl *rctrl;
+	const struct rstctl_line *line;
+	int i;
+
+	/* DT case goes through here */
+	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node)
+		return of_rstctl_get(dev, id);
+
+	/* non DT case does not support id == NULL */
+	if (id == NULL) {
+		dev_err(dev, "No reset ID supplied\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	/*
+	 * We search all the rstctl devices for a match
+	 * with the given label id
+	 */
+	mutex_lock(&rstctl_lock);
+	list_for_each_entry(rdev, &rstctl_dev_list, node) {
+		for (i = 0; i < rdev->rdesc->nlines; i++) {
+			line = &rdev->rdesc->lines[i];
+			if (strcmp(line->name, id) == 0) {
+				rctrl = rstctl_request_line(rdev, dev, line);
+				goto out;
+			}
+		}
+	}
+	rctrl = ERR_PTR(-ENODEV);
+out:
+	mutex_unlock(&rstctl_lock);
+
+	return rctrl;
+}
+EXPORT_SYMBOL(rstctl_get);
+
+void rstctl_put(struct rstctl *rctrl)
+{
+	struct rstctl_dev *rdev;
+	struct rstctl *rctrlt;
+
+	/* safe */
+	if (IS_ERR_OR_NULL(rctrl))
+		return;
+	rdev = rctrl->rdev;
+
+	mutex_lock(&rstctl_lock);
+	list_for_each_entry(rctrlt, &rdev->handles, node) {
+		if (rctrlt == rctrl)
+			goto found;
+	}
+	goto out;
+found:
+	/* release the reset */
+	reset_release(rctrl->rdev, rctrl->line);
+	list_del(&rctrl->node);
+	kfree(rctrl);
+out:
+	mutex_unlock(&rstctl_lock);
+}
+EXPORT_SYMBOL(rstctl_put);
+
+struct rstctl_dev *rstctl_register(struct device *dev,
+		const struct rstctl_desc *rdesc)
+{
+	struct rstctl_dev *rdev;
+
+	/* sanity check */
+	if (dev == NULL || rdesc == NULL || rdesc->ops == NULL)
+		return ERR_PTR(-EINVAL);
+
+	/* those three must be defined */
+	if (rdesc->ops->assert == NULL || rdesc->ops->deassert == NULL
+			|| rdesc->ops->pulse == NULL)
+		return ERR_PTR(-EINVAL);
+
+	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
+	if (rdev == NULL) {
+		dev_err(dev, "failed to alloc struct rstctl_dev\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	INIT_LIST_HEAD(&rdev->node);
+	rdev->dev = dev;
+	rdev->rdesc = rdesc;
+	INIT_LIST_HEAD(&rdev->handles);
+
+	mutex_lock(&rstctl_lock);
+	list_add_tail(&rdev->node, &rstctl_dev_list);
+	mutex_unlock(&rstctl_lock);
+
+	return rdev;
+}
+
+int rstctl_unregister(struct rstctl_dev *rdev)
+{
+	int err;
+
+	/* guard */
+	if (IS_ERR_OR_NULL(rdev))
+		return -EINVAL;
+
+	err = 0;
+
+	mutex_lock(&rstctl_lock);
+
+	if (!list_empty(&rdev->handles)) {
+		dev_err(rdev->dev, "%s still busy\n", rdev->rdesc->name);
+		err = -EBUSY;
+		goto out;
+	}
+	list_del(&rdev->node);
+
+	/* free */
+	kfree(rdev);
+
+	mutex_unlock(&rstctl_lock);
+
+out:
+	mutex_unlock(&rstctl_lock);
+	return err;
+}
+
+static int __init rstctl_init(void)
+{
+	pr_info("initialized rstctl subsystem\n");
+	return 0;
+}
+
+/* init early, resetting is needed pretty early */
+core_initcall(rstctl_init);
diff --git a/drivers/rstctl/rstctl-gpio.c b/drivers/rstctl/rstctl-gpio.c
new file mode 100644
index 0000000..4f3b5c1
--- /dev/null
+++ b/drivers/rstctl/rstctl-gpio.c
@@ -0,0 +1,259 @@
+/*
+ * Test driver for rstctl
+ *
+ * Author: Pantelis Antoniou <panto@antoniou-consulting.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/rstctl.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/pinctrl/consumer.h>
+
+struct gpio_data {
+	int gpio;
+	enum of_gpio_flags flags;
+	int hold_ns;
+};
+
+struct gpio_rctrl_info {
+	struct rstctl_dev *rdev;
+	struct rstctl_desc desc;
+	struct gpio_data *gpio_data;
+};
+
+int gpio_rctrl_request(struct rstctl_dev *rdev,
+		const struct rstctl_line *line)
+{
+	struct device *dev = rdev->dev;
+	const struct gpio_data *gd = line->data;
+	unsigned long flags;
+	int err;
+
+	dev_info(dev, "%s %s\n", __func__, line->name);
+
+	flags = GPIOF_DIR_OUT;
+	if (gd->flags & OF_GPIO_ACTIVE_LOW)
+		flags |= GPIOF_INIT_LOW;
+	else
+		flags |= GPIOF_INIT_HIGH;
+	/* XXX more flags ? */
+
+	err = devm_gpio_request_one(dev, gd->gpio, flags, line->name);
+	if (err != 0) {
+		dev_err(dev, "Failed to gpio_request\n");
+		return err;
+	}
+	return 0;
+}
+
+int gpio_rctrl_release(struct rstctl_dev *rdev,
+		const struct rstctl_line *line)
+{
+	struct device *dev = rdev->dev;
+	const struct gpio_data *gd = line->data;
+
+	dev_info(dev, "%s %s\n", __func__, line->name);
+	devm_gpio_free(dev, gd->gpio);
+	return 0;
+}
+
+int gpio_rctrl_assert(struct rstctl_dev *rdev,
+		const struct rstctl_line *line)
+{
+	struct device *dev = rdev->dev;
+	const struct gpio_data *gd = line->data;
+
+	dev_info(dev, "%s %s\n", __func__, line->name);
+	gpio_set_value(gd->gpio,
+			(gd->flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1);
+	return 0;
+}
+
+int gpio_rctrl_deassert(struct rstctl_dev *rdev,
+		const struct rstctl_line *line)
+{
+	struct device *dev = rdev->dev;
+	const struct gpio_data *gd = line->data;
+
+	dev_info(dev, "%s %s\n", __func__, line->name);
+	gpio_set_value(gd->gpio,
+			(gd->flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0);
+	return 0;
+}
+
+int gpio_rctrl_pulse(struct rstctl_dev *rdev,
+		const struct rstctl_line *line,
+		unsigned long hold_ns)
+{
+	struct device *dev = rdev->dev;
+	const struct gpio_data *gd = line->data;
+
+	dev_info(dev, "%s %s\n", __func__, line->name);
+
+	gpio_set_value(gd->gpio,
+			(gd->flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1);
+
+	if (hold_ns == 0)
+		hold_ns = gd->hold_ns;
+
+	if (hold_ns < 1000000)
+		ndelay(hold_ns);
+	else
+		mdelay(hold_ns / 1000000);
+
+	gpio_set_value(gd->gpio,
+			(gd->flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0);
+	return 0;
+}
+
+static const struct rstctl_ops gpio_rctrl_ops = {
+	.request	= gpio_rctrl_request,
+	.release	= gpio_rctrl_release,
+	.assert		= gpio_rctrl_assert,
+	.deassert	= gpio_rctrl_deassert,
+	.pulse		= gpio_rctrl_pulse,
+};
+
+static int gpio_rctrl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct gpio_rctrl_info *info;
+	struct rstctl_line *line, *lines;
+	struct gpio_data *gdata, *gd;
+	struct pinctrl *pinctrl;
+	int count, i, err;
+
+	/* we require OF */
+	if (!IS_ENABLED(CONFIG_OF) || np == NULL) {
+		dev_err(dev, "GPIO rstctl requires DT\n");
+		return -ENODEV;
+	}
+
+	pinctrl = devm_pinctrl_get_select_default(dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(dev, "Unable to select pin group\n");
+
+	count = of_gpio_named_count(np, "gpios");
+	if (count == 0) {
+		dev_err(dev, "GPIO rstctl found no GPIO resources\n");
+		return -ENODEV;
+	}
+
+	if (of_property_count_strings(np, "gpio-names") != count) {
+		dev_err(dev, "GPIO rstctl gpio-names property is invalid\n");
+		return -ENODEV;
+	}
+
+	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		dev_err(dev, "GPIO rstctl kzalloc failed\n");
+		return -ENOMEM;
+	}
+	lines = devm_kzalloc(dev, sizeof(*line) * count, GFP_KERNEL);
+	if (!lines) {
+		dev_err(dev, "GPIO rstctl kzalloc failed\n");
+		return -ENOMEM;
+	}
+	gdata = devm_kzalloc(dev, sizeof(*gdata) * count, GFP_KERNEL);
+	if (!gdata) {
+		dev_err(dev, "GPIO rstctl kzalloc failed\n");
+		return -ENOMEM;
+	}
+
+	info->desc.name = "gpio";
+	info->desc.ops = &gpio_rctrl_ops;
+	info->desc.nlines = count;
+	info->desc.lines = lines;
+	info->gpio_data = gdata;
+
+	for (i = 0; i < count; i++) {
+		line = &lines[i];
+		err = of_property_read_string_index(np, "gpio-names",
+				i, &line->name);
+		if (err != 0) {
+			dev_err(dev, "Failed to get string property\n");
+			return err;
+		}
+
+		gd = &gdata[i];
+		err = of_get_named_gpio_flags(np, "gpios", i, &gd->flags);
+		if (IS_ERR_VALUE(err)) {
+			dev_err(dev, "Failed to get named gpio\n");
+			return err;
+		}
+		gd->gpio = err;
+		gd->hold_ns = 1000;	/* 1us reset */
+		line->data = gd;
+	}
+
+	info->rdev = rstctl_register(&pdev->dev, &info->desc);
+	if (IS_ERR(info->rdev)) {
+		dev_err(&pdev->dev, "failed to register\n");
+		return PTR_ERR(info->rdev);
+	}
+	platform_set_drvdata(pdev, info);
+
+	dev_info(&pdev->dev, "loaded OK\n");
+
+	return 0;
+}
+
+static int gpio_rctrl_remove(struct platform_device *pdev)
+{
+	struct gpio_rctrl_info *info = platform_get_drvdata(pdev);
+	int err;
+
+	err = rstctl_unregister(info->rdev);
+	if (err == 0)
+		dev_info(&pdev->dev, "removed OK\n");
+
+	return err;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id gpio_rctrl_of_match[] = {
+	{ .compatible = "gpio-rctrl" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, gpio_rctrl_of_match);
+#endif
+
+static struct platform_driver gpio_rctrl_driver = {
+	.driver = {
+		.name = "gpio-rctrl",
+		.of_match_table = of_match_ptr(gpio_rctrl_of_match),
+	},
+	.probe = gpio_rctrl_probe,
+	.remove = gpio_rctrl_remove,
+};
+
+/*
+ * The reset control driver must be done very early.
+ */
+static int __init gpio_rctrl_drv_reg(void)
+{
+	return platform_driver_register(&gpio_rctrl_driver);
+}
+postcore_initcall(gpio_rctrl_drv_reg);
+
+MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
+MODULE_DESCRIPTION("rstctl GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rstctl/rstctl-test-consumer.c b/drivers/rstctl/rstctl-test-consumer.c
new file mode 100644
index 0000000..dd26ca1
--- /dev/null
+++ b/drivers/rstctl/rstctl-test-consumer.c
@@ -0,0 +1,82 @@
+/*
+ * Test consumer driver for rstctl
+ *
+ * Author: Pantelis Antoniou <panto@antoniou-consulting.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/rstctl.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+static int test_consumer_rctrl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rstctl *rctrl;
+
+	dev_info(dev, "Trying to get NULL (OF case only)\n");
+	rctrl = rstctl_get(dev, NULL);
+	if (IS_ERR(rctrl)) {
+		dev_info(dev, "Failed to get it\n");
+		return PTR_ERR(rctrl);
+	}
+
+	dev_info(dev, "Got it (%s:#%d name %s) label:%s\n",
+			rctrl->rdev->rdesc->name,
+			rctrl->line - rctrl->rdev->rdesc->lines,
+			rctrl->line->name, rctrl->label);
+
+	/* for now always assert */
+	rstctl_assert(rctrl);
+	platform_set_drvdata(pdev, rctrl);
+
+	dev_info(&pdev->dev, "loaded OK\n");
+	return 0;
+}
+
+static int test_consumer_rctrl_remove(struct platform_device *pdev)
+{
+	struct rstctl *rctrl = platform_get_drvdata(pdev);
+
+	rstctl_deassert(rctrl);
+	rstctl_put(rctrl);
+
+	dev_info(&pdev->dev, "unloaded OK\n");
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id test_consumer_rctrl_of_match[] = {
+	{ .compatible = "test-consumer-rctrl" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, test_consumer_rctrl_of_match);
+#endif
+
+static struct platform_driver test_consumer_rctrl_driver = {
+	.driver = {
+		.name = "test-consumer-rctrl",
+		.of_match_table = of_match_ptr(test_consumer_rctrl_of_match),
+	},
+	.probe = test_consumer_rctrl_probe,
+	.remove = test_consumer_rctrl_remove,
+};
+module_platform_driver(test_consumer_rctrl_driver);
+
+MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
+MODULE_DESCRIPTION("rstctl test consumer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rstctl/rstctl-test.c b/drivers/rstctl/rstctl-test.c
new file mode 100644
index 0000000..144c048
--- /dev/null
+++ b/drivers/rstctl/rstctl-test.c
@@ -0,0 +1,138 @@
+/*
+ * Test driver for rstctl
+ *
+ * Author: Pantelis Antoniou <panto@antoniou-consulting.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/rstctl.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+struct test_rctrl_info {
+	struct rstctl_dev *rdev;
+};
+
+int test_rctrl_request(struct rstctl_dev *rdev,
+		const struct rstctl_line *line)
+{
+	dev_info(rdev->dev, "%s %s\n", __func__, line->name);
+	return 0;
+}
+
+int test_rctrl_release(struct rstctl_dev *rdev,
+		const struct rstctl_line *line)
+{
+	dev_info(rdev->dev, "%s %s\n", __func__, line->name);
+	return 0;
+}
+
+int test_rctrl_assert(struct rstctl_dev *rdev,
+		const struct rstctl_line *line)
+{
+	dev_info(rdev->dev, "%s %s\n", __func__, line->name);
+	return 0;
+}
+
+int test_rctrl_deassert(struct rstctl_dev *rdev,
+		const struct rstctl_line *line)
+{
+	dev_info(rdev->dev, "%s %s\n", __func__, line->name);
+	return 0;
+}
+
+int test_rctrl_pulse(struct rstctl_dev *rdev,
+		const struct rstctl_line *line,
+		unsigned long hold_ns)
+{
+	dev_info(rdev->dev, "%s %s\n", __func__, line->name);
+	return 0;
+}
+
+static const struct rstctl_ops test_rctrl_ops = {
+	.request	= test_rctrl_request,
+	.release	= test_rctrl_release,
+	.assert		= test_rctrl_assert,
+	.deassert	= test_rctrl_deassert,
+	.pulse		= test_rctrl_pulse,
+};
+
+static const struct rstctl_line test_rctrl_lines[] = {
+	{ .name = "RESET1", },
+	{ .name = "RESET2", },
+};
+
+static const struct rstctl_desc test_rctrl_desc = {
+	.name	= "test",
+	.ops	= &test_rctrl_ops,
+	.nlines	= ARRAY_SIZE(test_rctrl_lines),
+	.lines	= test_rctrl_lines,
+};
+
+static int test_rctrl_probe(struct platform_device *pdev)
+{
+	struct test_rctrl_info *info;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->rdev = rstctl_register(&pdev->dev, &test_rctrl_desc);
+	if (IS_ERR(info->rdev)) {
+		dev_err(&pdev->dev, "failed to register\n");
+		return PTR_ERR(info->rdev);
+	}
+	platform_set_drvdata(pdev, info);
+
+	dev_info(&pdev->dev, "loaded OK\n");
+
+	return 0;
+}
+
+static int test_rctrl_remove(struct platform_device *pdev)
+{
+	struct test_rctrl_info *info = platform_get_drvdata(pdev);
+	int err;
+
+	err = rstctl_unregister(info->rdev);
+	if (err == 0)
+		dev_info(&pdev->dev, "removed OK\n");
+
+	return err;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id test_rctrl_of_match[] = {
+	{ .compatible = "test-rctrl" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, test_rctrl_of_match);
+#endif
+
+static struct platform_driver test_rctrl_driver = {
+	.driver = {
+		.name = "test-rctrl",
+		.of_match_table = of_match_ptr(test_rctrl_of_match),
+	},
+	.probe = test_rctrl_probe,
+	.remove = test_rctrl_remove,
+};
+module_platform_driver(test_rctrl_driver);
+
+MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
+MODULE_DESCRIPTION("rstctl test driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 6009714..e6d4878 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -72,6 +72,14 @@
 #define OMAP_RTC_KICK0_REG		0x6c
 #define OMAP_RTC_KICK1_REG		0x70
 
+#define OMAP_RTC_ALARM2_SECONDS_REG	0x80
+#define OMAP_RTC_ALARM2_MINUTES_REG	0x84
+#define OMAP_RTC_ALARM2_HOURS_REG	0x88
+#define OMAP_RTC_ALARM2_DAYS_REG	0x8c
+#define OMAP_RTC_ALARM2_MONTHS_REG	0x90
+#define OMAP_RTC_ALARM2_YEARS_REG	0x94
+#define OMAP_RTC_PMIC_REG		0x98
+
 /* OMAP_RTC_CTRL_REG bit fields: */
 #define OMAP_RTC_CTRL_SPLIT		(1<<7)
 #define OMAP_RTC_CTRL_DISABLE		(1<<6)
@@ -93,15 +101,21 @@
 #define OMAP_RTC_STATUS_BUSY            (1<<0)
 
 /* OMAP_RTC_INTERRUPTS_REG bit fields: */
+#define OMAP_RTC_INTERRUPTS_IT_ALARM2   (1<<4)
 #define OMAP_RTC_INTERRUPTS_IT_ALARM    (1<<3)
 #define OMAP_RTC_INTERRUPTS_IT_TIMER    (1<<2)
 
+/* OMAP_RTC_PMIC_REG bit fields: */
+#define OMAP_RTC_PMIC_POWER_EN_EN       (1<<16)
+
 /* OMAP_RTC_KICKER values */
 #define	KICK0_VALUE			0x83e70b13
 #define	KICK1_VALUE			0x95a4f1e0
 
 #define	OMAP_RTC_HAS_KICKER		0x1
 
+#define SHUTDOWN_TIME_SEC		2
+
 static void __iomem	*rtc_base;
 
 #define rtc_read(addr)		readb(rtc_base + (addr))
@@ -290,6 +304,56 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 	return 0;
 }
 
+/*
+ * rtc_power_off: Set the pmic power off sequence. The RTC generates
+ * pmic_pwr_enable control, which can be used to control an external
+ * PMIC.
+ */
+static void rtc_power_off(void)
+{
+	u32 val;
+	struct rtc_time tm;
+	unsigned long time;
+
+	/* Set PMIC power enable */
+	val = readl(rtc_base + OMAP_RTC_PMIC_REG);
+	writel(val | OMAP_RTC_PMIC_POWER_EN_EN, rtc_base + OMAP_RTC_PMIC_REG);
+
+	/* Read rtc time */
+	omap_rtc_read_time(NULL, &tm);
+
+	/* Convert Gregorian date to seconds since 01-01-1970 00:00:00 */
+	rtc_tm_to_time(&tm, &time);
+
+	/* Add shutdown time to the current value */
+	time += SHUTDOWN_TIME_SEC;
+
+	/* Convert seconds since 01-01-1970 00:00:00 to Gregorian date */
+	rtc_time_to_tm(time, &tm);
+
+	if (tm2bcd(&tm) < 0)
+		return;
+
+	pr_info("System will go to power_off state in approx. %d secs\n",
+			SHUTDOWN_TIME_SEC);
+
+	/*
+	 * pmic_pwr_enable is controlled by means of ALARM2 event. So here
+	 * programming alarm2 expiry time and enabling alarm2 interrupt
+	 */
+	rtc_write(tm.tm_sec, OMAP_RTC_ALARM2_SECONDS_REG);
+	rtc_write(tm.tm_min, OMAP_RTC_ALARM2_MINUTES_REG);
+	rtc_write(tm.tm_hour, OMAP_RTC_ALARM2_HOURS_REG);
+	rtc_write(tm.tm_mday, OMAP_RTC_ALARM2_DAYS_REG);
+	rtc_write(tm.tm_mon, OMAP_RTC_ALARM2_MONTHS_REG);
+	rtc_write(tm.tm_year, OMAP_RTC_ALARM2_YEARS_REG);
+
+	/* Enable alarm2 interrupt */
+	val = readl(rtc_base + OMAP_RTC_INTERRUPTS_REG);
+	writel(val | OMAP_RTC_INTERRUPTS_IT_ALARM2,
+				rtc_base + OMAP_RTC_INTERRUPTS_REG);
+}
+
 static struct rtc_class_ops omap_rtc_ops = {
 	.read_time	= omap_rtc_read_time,
 	.set_time	= omap_rtc_set_time,
@@ -327,12 +391,16 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 	struct resource		*res, *mem;
 	struct rtc_device	*rtc;
 	u8			reg, new_ctrl;
+	bool			pm_off = false;
 	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)
+	if (of_id) {
 		pdev->id_entry = of_id->data;
+		pm_off = of_property_read_bool(pdev->dev.of_node,
+					"ti,system-power-controller");
+	}
 
 	omap_rtc_timer = platform_get_irq(pdev, 0);
 	if (omap_rtc_timer <= 0) {
@@ -385,6 +453,10 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, rtc);
 	dev_set_drvdata(&rtc->dev, mem);
 
+	/* RTC power off */
+	if (pm_off && !pm_power_off)
+		pm_power_off = rtc_power_off;
+
 	/* clear pending irqs, and set 1/second periodic,
 	 * which we'll use instead of update irqs
 	 */
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index b610f52..2c02c02 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -102,6 +102,9 @@ struct omap2_mcspi_dma {
 
 	struct completion dma_tx_completion;
 	struct completion dma_rx_completion;
+
+	char dma_rx_ch_name[14];
+	char dma_tx_ch_name[14];
 };
 
 /* use PIO for small transfers, avoiding DMA setup/teardown overhead and
@@ -822,14 +825,23 @@ static int omap2_mcspi_request_dma(struct spi_device *spi)
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_SLAVE, mask);
 	sig = mcspi_dma->dma_rx_sync_dev;
-	mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
+
+	mcspi_dma->dma_rx =
+		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+						 &sig, &master->dev,
+						 mcspi_dma->dma_rx_ch_name);
+
 	if (!mcspi_dma->dma_rx) {
 		dev_err(&spi->dev, "no RX DMA engine channel for McSPI\n");
 		return -EAGAIN;
 	}
 
 	sig = mcspi_dma->dma_tx_sync_dev;
-	mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
+	mcspi_dma->dma_tx =
+		dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+						 &sig, &master->dev,
+						 mcspi_dma->dma_tx_ch_name);
+
 	if (!mcspi_dma->dma_tx) {
 		dev_err(&spi->dev, "no TX DMA engine channel for McSPI\n");
 		dma_release_channel(mcspi_dma->dma_rx);
@@ -1223,29 +1235,42 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
 		goto free_master;
 
 	for (i = 0; i < master->num_chipselect; i++) {
-		char dma_ch_name[14];
+		char *dma_rx_ch_name = mcspi->dma_channels[i].dma_rx_ch_name;
+		char *dma_tx_ch_name = mcspi->dma_channels[i].dma_tx_ch_name;
 		struct resource *dma_res;
 
-		sprintf(dma_ch_name, "rx%d", i);
-		dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
-							dma_ch_name);
-		if (!dma_res) {
-			dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
-			status = -ENODEV;
-			break;
-		}
+		sprintf(dma_rx_ch_name, "rx%d", i);
+		if (!pdev->dev.of_node) {
+			dma_res =
+				platform_get_resource_byname(pdev,
+							     IORESOURCE_DMA,
+							     dma_rx_ch_name);
+			if (!dma_res) {
+				dev_dbg(&pdev->dev,
+					"cannot get DMA RX channel\n");
+				status = -ENODEV;
+				break;
+			}
 
-		mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
-		sprintf(dma_ch_name, "tx%d", i);
-		dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
-							dma_ch_name);
-		if (!dma_res) {
-			dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
-			status = -ENODEV;
-			break;
+			mcspi->dma_channels[i].dma_rx_sync_dev =
+				dma_res->start;
 		}
+		sprintf(dma_tx_ch_name, "tx%d", i);
+		if (!pdev->dev.of_node) {
+			dma_res =
+				platform_get_resource_byname(pdev,
+							     IORESOURCE_DMA,
+							     dma_tx_ch_name);
+			if (!dma_res) {
+				dev_dbg(&pdev->dev,
+					"cannot get DMA TX channel\n");
+				status = -ENODEV;
+				break;
+			}
 
-		mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
+			mcspi->dma_channels[i].dma_tx_sync_dev =
+				dma_res->start;
+		}
 	}
 
 	if (status < 0)
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index 0ecf22b..f78b254 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -164,6 +164,16 @@ config BFIN_JTAG_COMM_CONSOLE
 	bool "Console on Blackfin JTAG"
 	depends on BFIN_JTAG_COMM=y
 
+config JHD629_I2C
+	bool "JHD629 I2C support"
+	depends on I2C && OF
+	select SERIAL_CORE
+	default n
+	help
+	  This selects support for a pseudo TTY on I2Ced JHD629
+
+	  Say Y here if you want to support this.
+
 config SERIAL_NONSTANDARD
 	bool "Non-standard serial port support"
 	depends on HAS_IOMEM
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile
index 2953059..d5df8f5 100644
--- a/drivers/tty/Makefile
+++ b/drivers/tty/Makefile
@@ -29,3 +29,6 @@ obj-$(CONFIG_SYNCLINK)		+= synclink.o
 obj-$(CONFIG_PPC_EPAPR_HV_BYTECHAN) += ehv_bytechan.o
 
 obj-y += ipwireless/
+
+# JHD pseudo TTY
+obj-$(CONFIG_JHD629_I2C)	+= jhd629-i2c.o
diff --git a/drivers/tty/jhd629-i2c.c b/drivers/tty/jhd629-i2c.c
new file mode 100644
index 0000000..7fd4c88
--- /dev/null
+++ b/drivers/tty/jhd629-i2c.c
@@ -0,0 +1,964 @@
+/*
+ * jhd629-i2c.c: Serial driver (over I2C) for the JHD629 series of modules
+ *
+ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.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/module.h>
+#include <linux/device.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/regmap.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/idr.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <asm/bitops.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/err.h>
+
+#define JHD629_MAJOR			204
+#define JHD629_MINOR			220
+
+/* maximum 4 instances... (meh; tty layer is archaic) */
+#define JHD629_MAX_INSTANCES		4
+
+/* just one byte */
+#define JHD629_FIFO_SIZE		1
+
+struct jhd629_port {
+	int id;
+	struct i2c_client 	*client;
+
+	struct uart_driver	uart;
+	struct uart_port	port;
+
+	const char		*name;
+
+	struct workqueue_struct	*tx_wq;
+	struct work_struct	tx_work;
+	struct workqueue_struct	*rx_wq;
+	struct work_struct	rx_work;
+
+	struct mutex		lock;
+
+	int 			keypad_irq;
+	char			keypad_gpio_name[32];
+	struct timer_list	poll_timer;
+	unsigned int		poll_timer_running : 1;
+
+	/* escape in progress */
+	int			esc_mode;
+#define ESC_NONE	0
+#define ESC_ESC		1
+#define ESC_LBRACKET	2
+	int			esc_next;
+	char			esc_buf[64];
+
+	/* configuration data */
+	int			rows, cols;
+	char			keymap[16 + 1];	/* 4x4 + 1 '\0' */
+	int			keypad_gpio;
+	int			poll_period;
+};
+
+static DEFINE_IDA(jhd629_ida);
+
+static void jhd629_send_byte(struct jhd629_port *s, u8 ch)
+{
+	i2c_smbus_write_byte(s->client, ch);
+}
+
+static int jhd629_recv_byte(struct jhd629_port *s)
+{
+	return i2c_smbus_read_byte(s->client);
+}
+
+static void jhd629_send_block(struct jhd629_port *s, const void *buf, int len)
+{
+	const u8 *p;
+
+	p = buf;
+	while (len-- > 0)
+		jhd629_send_byte(s, *p++);
+}
+
+static void jhd629_send_str(struct jhd629_port *s, const char *str)
+{
+	jhd629_send_block(s, str, strlen(str));
+}
+
+static void jhd629_handle_escape(struct jhd629_port *s)
+{
+	char esc_ch;
+	char *ep, *epe, *epr, *epnext;
+	int num = 0, row = 0, col = 0, qmark = 0, num_exists = 0;
+	char xmitbuf[8];
+
+	if (s->esc_mode == ESC_NONE || s->esc_next <= 0)
+		goto esc_end;
+
+	/* fast access to escape buffer */
+	ep = s->esc_buf;
+
+	/* same to the end of the buffer */
+	epe = s->esc_buf + s->esc_next;
+
+	/* single character escapes */
+	if (ep[0] != '[') {
+		esc_ch = ep[0];
+
+		switch (esc_ch) {
+		case 'c':
+			dev_dbg(s->port.dev, "esc-RESET\n");
+			xmitbuf[0] = 0x1b;
+			xmitbuf[1] = 'c';
+			jhd629_send_block(s, xmitbuf, 2);
+			break;
+		case 'a':
+			dev_dbg(s->port.dev, "esc-ACK\n");
+			/* I2C does not have ACK */
+			break;
+		default:
+			/* nothing */
+			break;
+		}
+	} else {
+
+		esc_ch = epe[-1];	/* last character */
+
+		dev_dbg(s->port.dev, "handle escape 0x1b %c\n", esc_ch);
+		num = 1;
+
+		epr = ep + 1;
+		qmark = 0;
+		if (*epr == '?') {
+			epr++;
+			qmark = 1;
+		}
+		/* digit?, read it */
+		if (*epr >= '0' && *epr <= '9') {
+			num_exists = 1;
+			num = simple_strtoul(epr, &epnext, 10);
+			if (*epnext == ',' || *epnext == ';') {
+				row = num;
+				col = simple_strtoul(epnext + 1, NULL, 10);
+			}
+		} else {
+			num_exists = 0;
+			num = 1;
+			row = 1;
+			col = 1;
+		}
+
+		if (!qmark) {
+			switch (esc_ch) {
+			case 'A':
+				dev_dbg(s->port.dev, "esc-UP%d\n", num);
+				while (num-- > 0)
+					jhd629_send_str(s, "\x1b\x20");
+				break;
+			case 'B':
+				dev_dbg(s->port.dev, "esc-DOWN%d\n", num);
+				while (num-- > 0)
+					jhd629_send_str(s, "\x1b\x21");
+				break;
+			case 'C':
+				dev_dbg(s->port.dev, "esc-RIGHT%d\n", num);
+				while (num-- > 0)
+					jhd629_send_str(s, "\x1b\x22");
+				break;
+			case 'D':
+				dev_dbg(s->port.dev, "esc-RIGHT%d\n", num);
+				while (num-- > 0)
+					jhd629_send_str(s, "\x1b\x23");
+				break;
+			case 'H':
+				dev_dbg(s->port.dev, "esc-HOME(%d;%d)\n", row, col);
+
+				if (col != 1 || row != 1) {
+					xmitbuf[0] = 0x1b;
+					xmitbuf[1] = 0x24;
+					xmitbuf[2] = (u8)row;
+					xmitbuf[3] = (u8)col;
+					jhd629_send_block(s, xmitbuf, 4);
+				} else
+					jhd629_send_str(s, "\x1b\x25");
+				break;
+
+			case 'E':
+				dev_dbg(s->port.dev, "esc-DIRECT%d\n", num);
+				xmitbuf[0] = 0x1b;
+				xmitbuf[1] = 0x01;
+				xmitbuf[2] = num;
+				jhd629_send_block(s, xmitbuf, 3);
+				break;
+
+			case 'L':
+				dev_dbg(s->port.dev, "esc-LINES%d\n", num);
+				xmitbuf[0] = 0x1b;
+				xmitbuf[1] = 0x30;
+				xmitbuf[2] = num;
+				jhd629_send_block(s, xmitbuf, 3);
+				break;
+
+			case 'c':
+				dev_dbg(s->port.dev, "esc-COLUMNS%d\n", num);
+				xmitbuf[0] = 0x1b;
+				xmitbuf[1] = 0x31;
+				xmitbuf[2] = num;
+				jhd629_send_block(s, xmitbuf, 3);
+				break;
+
+			case 'b':
+				dev_dbg(s->port.dev, "esc-BAUD%d\n", num);
+				/* ignored */
+				break;
+
+			case 'd':
+				dev_dbg(s->port.dev, "esc-LF/CR%d\n", num);
+				/* ignored */
+				break;
+
+			case 'x':
+				dev_dbg(s->port.dev, "esc-VERTSCROLL%d\n", num);
+				xmitbuf[0] = 0x1b;
+				xmitbuf[1] = 0x45;
+				xmitbuf[2] = num;
+				jhd629_send_block(s, xmitbuf, 3);
+				break;
+
+			case 'a':
+				dev_dbg(s->port.dev, "esc-I2CADDR%d\n", num);
+				xmitbuf[0] = 0x1b;
+				xmitbuf[1] = 0x42;
+				xmitbuf[2] = 0x55;
+				xmitbuf[3] = 0x37;
+				xmitbuf[4] = num;
+				jhd629_send_block(s, xmitbuf, 5);
+				break;
+
+			case 'J':
+				if (num == 4) {
+					dev_dbg(s->port.dev, "esc-RESETEEPROM\n");
+					jhd629_send_str(s, "\x1b\x44");
+				} else if (num == 2) {
+					dev_dbg(s->port.dev, "esc-CLEARSCR\n");
+					jhd629_send_str(s, "\x1b\x50");
+				}
+				break;
+			case 'K':
+				if (!num_exists) {
+					dev_dbg(s->port.dev, "esc-CLRLINERIGHT\n");
+					jhd629_send_str(s, "\x1b\x51");
+				} else if (num == 1) {
+					dev_dbg(s->port.dev, "esc-CLRLINELEFT\n");
+					jhd629_send_str(s, "\x1b\x52");
+				} else if (num == 2) {
+					dev_dbg(s->port.dev, "esc-CLRLINE\n");
+					jhd629_send_str(s, "\x1b\x53");
+				}
+				break;
+			}
+		} else {
+			switch (esc_ch) {
+			case 'I':
+				if (num == 25) {
+					dev_dbg(s->port.dev, "esc-CURSOROFF\n");
+					xmitbuf[0] = 0x1b;
+					xmitbuf[1] = 0x01;
+					xmitbuf[2] = 0x0c;
+					jhd629_send_block(s, xmitbuf, 3);
+				} else if (num == 26) {
+					dev_dbg(s->port.dev, "esc-BACKLIGHTOFF\n");
+					xmitbuf[0] = 0x1b;
+					xmitbuf[1] = 0x03;
+					xmitbuf[2] = 0x00;
+					jhd629_send_block(s, xmitbuf, 3);
+				}
+				break;
+			case 'h':
+				if (num == 25) {
+					dev_dbg(s->port.dev, "esc-CURSORON\n");
+					xmitbuf[0] = 0x1b;
+					xmitbuf[1] = 0x01;
+					xmitbuf[2] = 0x0e;
+					jhd629_send_block(s, xmitbuf, 3);
+				} else if (num == 26) {
+					dev_dbg(s->port.dev, "esc-BACKLIGHTON\n");
+					xmitbuf[0] = 0x1b;
+					xmitbuf[1] = 0x03;
+					xmitbuf[2] = 0x01;
+					jhd629_send_block(s, xmitbuf, 3);
+				}
+				break;
+			case 'd':
+				break;
+			case 'f':
+				break;
+			case 'S':
+				break;
+			}
+		}
+	}
+
+esc_end:
+	s->esc_mode = ESC_NONE;
+	s->esc_next = 0;
+}
+
+static void jh629_cancel_escape(struct jhd629_port *s)
+{
+	s->esc_mode = ESC_NONE;
+	s->esc_next = 0;
+}
+
+/* lock should be taken */
+static void jhd629_tx_char(struct jhd629_port *s, int ch)
+{
+	/* normal, non-escaped output */
+	if (s->esc_mode == ESC_NONE) {
+		switch (ch) {
+		case 0x1b:	/* ESC */
+			s->esc_mode = ESC_ESC;
+			s->esc_next = 0;
+			s->esc_buf[s->esc_next] = '\0';
+			break;
+		case '\n':	/* LF */
+			jhd629_send_str(s, "\x1b\x0a");
+			break;
+		case '\r':	/* CR */
+			jhd629_send_str(s, "\x1b\x0d");
+			break;
+		case '\b':	/* BS */
+			/* ignored */
+			break;
+		default:
+			jhd629_send_byte(s, ch);
+			break;
+		}
+		return;
+	}
+
+	/* an escaped mode */
+
+	/* append to escape buffer */
+	if (s->esc_next < ARRAY_SIZE(s->esc_buf) - 1) {
+		s->esc_buf[s->esc_next++] = ch;
+		s->esc_buf[s->esc_next] = '\0';
+	}
+
+	switch (s->esc_mode) {
+
+	case ESC_NONE:
+		/* never happens */
+		break;
+
+	case ESC_ESC:
+		switch (ch) {
+		case '[':	/* left bracket */
+			s->esc_mode = ESC_LBRACKET;
+			break;
+		case 'a':
+		case 'c':
+			jhd629_handle_escape(s);
+			break;
+		default:
+			/* unknown escape sequence (ignore) */
+			jh629_cancel_escape(s);
+			break;
+		}
+		break;
+
+	case ESC_LBRACKET:
+		switch (ch) {
+		case '0': case '1': case '2': case '3': case '4':
+		case '5': case '6': case '7': case '8': case '9':
+		case ';': case '?': case ',':
+			break;
+		default:
+			jhd629_handle_escape(s);
+			break;
+		}
+	}
+}
+
+static void jhd629_handle_rx(struct jhd629_port *s)
+{
+	struct tty_struct *tty = tty_port_tty_get(&s->port.state->port);
+	int rx_len, rx_cnt, ch;
+	int row, col;
+
+	if (!tty)
+		return;
+
+	/* find out how many keys in the buffer */
+	rx_cnt = 0;
+	for (;;) {
+		jhd629_send_byte(s, 0x1b);
+		jhd629_send_byte(s, 0x10);
+		rx_len = jhd629_recv_byte(s);
+		if (rx_len <= 0)
+			break;
+
+		/* now get key scan code */
+		while (rx_len--) {
+
+			jhd629_send_byte(s, 0x1b);
+			jhd629_send_byte(s, 0x11);
+			ch = jhd629_recv_byte(s);
+			if (ch <= 0)
+				continue;
+
+			row = ffz(ch & 0xf);
+			col = ffz((ch >> 4) & 0xf);
+
+			ch = s->keymap[row * 4 + col];
+
+			rx_cnt++;
+
+			s->port.icount.rx++;
+			if (uart_handle_sysrq_char(s->port, ch))
+				continue;
+
+			dev_dbg(s->port.dev, "rx 0x%02x\n", (int)ch & 0xff);
+
+			uart_insert_char(&s->port, 0, 0, ch, TTY_NORMAL);
+		}
+	}
+
+	if (rx_cnt > 0)
+		tty_flip_buffer_push(tty);
+
+	tty_kref_put(tty);
+}
+
+static void jhd629_handle_tx(struct jhd629_port *s)
+{
+	struct circ_buf *xmit = &s->port.state->xmit;
+	unsigned int to_send;
+
+	if (unlikely(s->port.x_char)) {
+
+		jhd629_tx_char(s, s->port.x_char);
+
+		s->port.icount.tx++;
+		s->port.x_char = 0;
+		return;
+	}
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port))
+		return;
+
+	/* Get length of data pending in circular buffer */
+	to_send = uart_circ_chars_pending(xmit);
+	if (likely(to_send)) {
+
+		/* Add data to send */
+		s->port.icount.tx += to_send;
+		while (to_send--) {
+
+			jhd629_tx_char(s, xmit->buf[xmit->tail]);
+
+			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		};
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&s->port);
+}
+
+static void jhd629_tx_wq_proc(struct work_struct *ws)
+{
+	struct jhd629_port *s = container_of(ws, struct jhd629_port, tx_work);
+
+	mutex_lock(&s->lock);
+	jhd629_handle_tx(s);
+	mutex_unlock(&s->lock);
+}
+
+static void jhd629_rx_wq_proc(struct work_struct *ws)
+{
+	struct jhd629_port *s = container_of(ws, struct jhd629_port, rx_work);
+
+	mutex_lock(&s->lock);
+	jhd629_handle_rx(s);
+	mutex_unlock(&s->lock);
+}
+
+static void jhd629_start_tx(struct uart_port *port)
+{
+	struct jhd629_port *s = container_of(port, struct jhd629_port, port);
+
+	queue_work(s->tx_wq, &s->tx_work);
+}
+
+static void jhd629_stop_tx(struct uart_port *port)
+{
+	/* Do nothing */
+}
+
+static void jhd629_stop_rx(struct uart_port *port)
+{
+	struct jhd629_port *s = container_of(port, struct jhd629_port, port);
+
+	mutex_lock(&s->lock);
+
+	/* clear keypad buffer */
+	jhd629_send_block(s, "\x1b\x14", 2);
+	if (s->poll_timer_running) {
+		del_timer_sync(&s->poll_timer);
+		s->poll_timer_running = 0;
+	}
+
+	mutex_unlock(&s->lock);
+}
+
+static unsigned int jhd629_tx_empty(struct uart_port *port)
+{
+	/* transmitter is always empty */
+	return TIOCSER_TEMT;
+}
+
+static void jhd629_enable_ms(struct uart_port *port)
+{
+	/* Modem status not supported */
+}
+
+static unsigned int jhd629_get_mctrl(struct uart_port *port)
+{
+	/* DCD and DSR are not wired and CTS/RTS is handled automatically
+	 * so just indicate DSR and CAR asserted
+	 */
+	return TIOCM_DSR | TIOCM_CAR;
+}
+
+static void jhd629_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	/* DCD and DSR are not wired and CTS/RTS is hadnled automatically
+	 * so do nothing
+	 */
+}
+
+static void jhd629_break_ctl(struct uart_port *port, int break_state)
+{
+	/* nothing */
+}
+
+static void jhd629_set_termios(struct uart_port *port,
+				struct ktermios *termios,
+				struct ktermios *old)
+{
+	struct jhd629_port *s = container_of(port, struct jhd629_port, port);
+
+	/* we don't support much... */
+
+	mutex_lock(&s->lock);
+
+	/* Mask termios capabilities we don't support */
+	termios->c_cflag &= ~CMSPAR;
+	termios->c_iflag &= ~IXANY;
+
+	/* Set read status mask */
+	port->read_status_mask = 0;
+
+	/* Set status ignore mask */
+	port->ignore_status_mask = 0;
+
+	mutex_unlock(&s->lock);
+}
+
+static int jhd629_startup(struct uart_port *port)
+{
+	struct jhd629_port *s = container_of(port, struct jhd629_port, port);
+
+	mutex_lock(&s->lock);
+
+	/* clear keypad buffer */
+	jhd629_send_block(s, "\x1b\x14", 2);
+
+	if (s->keypad_irq < 0 && !s->poll_timer_running) {
+		s->poll_timer.expires = jiffies +
+				msecs_to_jiffies(s->poll_period);
+		s->poll_timer_running = 1;
+		add_timer(&s->poll_timer);
+	}
+
+	mutex_unlock(&s->lock);
+
+	return 0;
+}
+
+static void jhd629_shutdown(struct uart_port *port)
+{
+	struct jhd629_port *s = container_of(port, struct jhd629_port, port);
+
+	mutex_lock(&s->lock);
+
+	if (s->poll_timer_running) {
+		del_timer_sync(&s->poll_timer);
+		s->poll_timer_running = 0;
+	}
+
+	mutex_unlock(&s->lock);
+}
+
+static const char *jhd629_type(struct uart_port *port)
+{
+	struct jhd629_port *s = container_of(port, struct jhd629_port, port);
+
+	return (port->type == PORT_JHD629) ? s->name : NULL;
+}
+
+static int jhd629_request_port(struct uart_port *port)
+{
+	/* Do nothing */
+	return 0;
+}
+
+static void jhd629_release_port(struct uart_port *port)
+{
+	/* Do nothing */
+}
+
+static void jhd629_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE)
+		port->type = PORT_JHD629;
+}
+
+static int jhd629_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	if (ser->type == PORT_UNKNOWN || ser->type == PORT_JHD629)
+		return 0;
+
+	return -EINVAL;
+}
+
+static struct uart_ops jhd629_ops = {
+	.tx_empty	= jhd629_tx_empty,
+	.set_mctrl	= jhd629_set_mctrl,
+	.get_mctrl	= jhd629_get_mctrl,
+	.stop_tx	= jhd629_stop_tx,
+	.start_tx	= jhd629_start_tx,
+	.stop_rx	= jhd629_stop_rx,
+	.enable_ms	= jhd629_enable_ms,
+	.break_ctl	= jhd629_break_ctl,
+	.startup	= jhd629_startup,
+	.shutdown	= jhd629_shutdown,
+	.set_termios	= jhd629_set_termios,
+	.type		= jhd629_type,
+	.request_port	= jhd629_request_port,
+	.release_port	= jhd629_release_port,
+	.config_port	= jhd629_config_port,
+	.verify_port	= jhd629_verify_port,
+};
+
+static irqreturn_t jhd629_keypad_irq(int irq, void *dev_id)
+{
+	struct jhd629_port *s = dev_id;
+
+	/* just queue the check */
+	queue_work(s->rx_wq, &s->rx_work);
+
+	return IRQ_HANDLED;
+}
+
+static void jhd629_poll_timer(unsigned long ptr)
+{
+	struct jhd629_port *s = (void *)ptr;
+
+	/* check for input in the rx work queue */
+	queue_work(s->rx_wq, &s->rx_work);
+
+	/* schedule next timer poll */
+	s->poll_timer.expires = jiffies +
+			msecs_to_jiffies(s->poll_period);
+	add_timer(&s->poll_timer);
+}
+
+/* we only support DT for now */
+static int jhd629_setup(struct jhd629_port *s)
+{
+	struct device_node *node = s->client->dev.of_node;
+	const char *keymap;
+	static const char *default_keymap =
+		"123A"
+		"456B"
+		"789C"
+		"*0#D";
+	u32 val;
+
+	/* rows */
+	if (of_property_read_u32(node, "rows", &val) == 0)
+		s->rows = val;
+	else
+		s->rows = 4;
+
+	/* columns */
+	if (of_property_read_u32(node, "columns", &val) == 0)
+		s->cols = val;
+	else
+		s->cols = 20;
+
+	/* keymap */
+	if (of_property_read_string(node, "keymap", &keymap) != 0)
+		keymap = default_keymap;
+	strncpy(s->keymap, keymap, sizeof(s->keymap));
+
+	/* poll_period */
+	if (of_property_read_u32(node, "poll-period", &val) == 0)
+		s->poll_period = val;
+	else
+		s->poll_period = 250;
+
+	s->keypad_gpio = of_get_gpio_flags(node, 0, NULL);
+	if (IS_ERR_VALUE(s->keypad_gpio))
+		s->keypad_gpio = -1; /* no gpio, switch to polling */
+
+	return 0;
+}
+
+static int jhd629_apply_irq_config(struct jhd629_port *s)
+{
+	int err;
+
+	snprintf(s->keypad_gpio_name, sizeof(s->keypad_gpio_name) - 1,
+			"jhd629:%d", s->id);
+
+	err = gpio_request_one(s->keypad_gpio,
+			GPIOF_DIR_IN | GPIOF_EXPORT,
+			s->keypad_gpio_name);
+	if (err != 0) {
+		dev_err(s->port.dev, "Failed to request keypad INT\n");
+		goto err_no_req;
+	}
+
+	s->keypad_irq = gpio_to_irq(s->keypad_gpio);
+	if (IS_ERR_VALUE(s->keypad_irq)) {
+		dev_err(s->port.dev, "unable to get keypad IRQ\n");
+		err = s->keypad_irq;
+		s->keypad_irq = -1;
+		goto err_no_irq;
+	}
+
+	err = request_irq(s->keypad_irq, jhd629_keypad_irq,
+			IRQF_TRIGGER_FALLING | IRQF_SHARED,
+			s->keypad_gpio_name, s);
+	if (err != 0) {
+		dev_err(s->port.dev, "unable to request keypad irq\n");
+		goto err_no_irq;
+	}
+
+	dev_dbg(s->port.dev, "Using keyboard irq #%d\n",
+			s->keypad_irq);
+	return 0;
+
+err_no_irq:
+	s->keypad_irq = -1;
+	gpio_free(s->keypad_gpio);
+err_no_req:
+	s->keypad_gpio = -1;
+	return err;
+}
+
+static int jhd629_apply_config(struct jhd629_port *s)
+{
+	int err;
+
+	/* clear screen */
+	jhd629_send_block(s, "\x1b\x50", 2);
+
+	/* columns */
+	jhd629_send_block(s, "\x1b\x31", 2);
+	jhd629_send_byte(s, s->cols);
+
+	/* rows */
+	jhd629_send_block(s, "\x1b\x30", 2);
+	jhd629_send_byte(s, s->rows);
+
+	/* try to apply the irq config (if possible) */
+	if (s->keypad_gpio >= 0) {
+		err = jhd629_apply_irq_config(s);
+		if (err == 0)
+			return 0;
+	}
+
+	dev_dbg(s->port.dev, "Using polling period of %dms\n",
+			s->poll_period);
+
+	return 0;
+}
+
+static int jhd629_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	/* struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); */
+	struct device *dev = &client->dev;
+	struct jhd629_port *s = NULL;
+	int ret = 0;
+	struct pinctrl *pinctrl;
+
+	/* this better be early */
+	pinctrl = devm_pinctrl_get_select_default(dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(dev,
+			"pins are not configured from the driver\n");
+
+	/* Alloc port structure */
+	s = devm_kzalloc(dev, sizeof(struct jhd629_port), GFP_KERNEL);
+	if (!s) {
+		dev_err(dev, "Error allocating port structure\n");
+		return -ENOMEM;
+	}
+	s->id = -1;
+
+	s->client = client;
+	i2c_set_clientdata(client, s);
+
+	mutex_init(&s->lock);
+
+	s->id = ida_simple_get(&jhd629_ida, 0, JHD629_MAX_INSTANCES, GFP_KERNEL);
+	if (s->id < 0) {
+		dev_err(dev, "Failed to get port ID (too many instances?)\n");
+		goto err_out;
+	}
+
+	/* Register UART driver */
+	s->uart.owner		= THIS_MODULE;
+	s->uart.driver_name	= dev_name(dev);
+	s->uart.dev_name	= "ttyJHD";
+	s->uart.major		= JHD629_MAJOR;
+	s->uart.minor		= JHD629_MINOR + s->id;
+	s->uart.nr		= 1;
+	s->name			= "JHD629";
+	ret = uart_register_driver(&s->uart);
+	if (ret != 0) {
+		dev_err(dev, "Registering UART driver failed\n");
+		goto err_out;
+	}
+
+	/* Initialize workqueue for start TX */
+	s->tx_wq = create_freezable_workqueue(dev_name(dev));
+	INIT_WORK(&s->tx_work, jhd629_tx_wq_proc);
+
+	/* Initialize workqueue for RX polling */
+	s->rx_wq = create_freezable_workqueue(dev_name(dev));
+	INIT_WORK(&s->rx_work, jhd629_rx_wq_proc);
+
+	init_timer(&s->poll_timer);
+	s->poll_timer.function = jhd629_poll_timer;
+	s->poll_timer.data = (unsigned long)s;
+
+	s->keypad_gpio = -1;
+	s->keypad_irq = -1;
+
+	/* Initialize UART port data */
+	s->port.line		= 0;
+	s->port.dev		= dev;
+	s->port.irq		= -1;
+	s->port.type		= PORT_JHD629;
+	s->port.fifosize	= 1;
+	s->port.flags		= UPF_SKIP_TEST | UPF_FIXED_TYPE;
+	s->port.iotype		= UPIO_PORT;
+	s->port.membase		= (void __iomem *)0xffffffff; /* Bogus value */
+	s->port.uartclk		= 9600 * 16;	/* emulate a 9600 baud port */
+	s->port.ops		= &jhd629_ops;
+	ret = uart_add_one_port(&s->uart, &s->port);
+	if (ret != 0) {
+		dev_err(s->port.dev, "Adding a port failed\n");
+		goto err_port;
+	}
+
+	ret = jhd629_setup(s);
+	if (ret != 0) {
+		dev_err(s->port.dev, "jhd629_setup failed\n");
+		goto err_port;
+	}
+
+	ret = jhd629_apply_config(s);
+	if (ret != 0) {
+		dev_err(s->port.dev, "jhd629_apply_config failed\n");
+		goto err_port;
+	}
+
+	dev_dbg(s->port.dev, "Added port #%d\n", s->id);
+
+	return 0;
+
+err_port:
+	uart_remove_one_port(&s->uart, &s->port);
+
+err_out:
+	if (s != NULL) {
+		if (s->id >= 0) {
+			ida_simple_remove(&jhd629_ida, s->id);
+			s->id = -1;
+		}
+	}
+	i2c_set_clientdata(client, NULL);
+
+	return ret;
+}
+
+static int jhd629_remove(struct i2c_client *client)
+{
+	struct jhd629_port *s = i2c_get_clientdata(client);
+
+	dev_dbg(s->port.dev, "Removing port #%d\n", s->id);
+
+	if (s->keypad_irq >= 0) {
+		free_irq(s->keypad_irq, s);
+		gpio_free(s->keypad_gpio);
+	}
+
+	if (s->poll_timer_running) {
+		del_timer_sync(&s->poll_timer);
+		s->poll_timer_running = 0;
+	}
+
+	destroy_workqueue(s->rx_wq);
+	destroy_workqueue(s->tx_wq);
+
+	uart_remove_one_port(&s->uart, &s->port);
+	uart_unregister_driver(&s->uart);
+
+	ida_simple_remove(&jhd629_ida, s->id);
+
+	i2c_set_clientdata(client, NULL);
+
+	return 0;
+}
+
+static const struct i2c_device_id jhd629_id_table[] = {
+	{ "jhd629" },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, jhd629_id_table);
+
+static struct i2c_driver jhd629_driver = {
+	.driver = {
+		.name	= "jhd629-i2c",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= jhd629_probe,
+	.remove		= jhd629_remove,
+	.id_table	= jhd629_id_table,
+};
+module_i2c_driver(jhd629_driver);
+
+MODULE_AUTHOR("Pantelis Antoniou <panto@antoniou-consulting.com>");
+MODULE_DESCRIPTION("JHD629-i2c driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index f56d185..a991a08 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -112,10 +112,10 @@ config UIO_NETX
 
 config UIO_PRUSS
 	tristate "Texas Instruments PRUSS driver"
-	depends on ARCH_DAVINCI_DA850
+	depends on ARCH_DAVINCI_DA850 || SOC_AM33XX
 	select GENERIC_ALLOCATOR
 	help
-	  PRUSS driver for OMAPL138/DA850/AM18XX devices
+	  PRUSS driver for OMAPL138/DA850/AM18XX and AM33XX devices
 	  PRUSS driver requires user space components, examples and user space
 	  driver is available from below SVN repo - you may use anonymous login
 
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
index 6e2ab00..54f4781 100644
--- a/drivers/uio/uio_pruss.c
+++ b/drivers/uio/uio_pruss.c
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
+#include <linux/of_gpio.h>
 #include <linux/uio_driver.h>
 #include <linux/platform_data/uio_pruss.h>
 #include <linux/io.h>
@@ -26,6 +27,11 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/genalloc.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
 
 #define DRV_NAME "pruss_uio"
 #define DRV_VERSION "1.0"
@@ -72,6 +78,32 @@ struct uio_pruss_dev {
 	struct gen_pool *sram_pool;
 };
 
+static ssize_t store_sync_ddr(struct device *dev, struct device_attribute *attr,  char *buf, size_t count) {
+	struct uio_pruss_dev *gdev;
+	gdev = dev_get_drvdata(dev);
+	dma_sync_single_for_cpu(dev, gdev->ddr_paddr, extram_pool_sz, DMA_FROM_DEVICE);
+	return count;
+}
+static DEVICE_ATTR(sync_ddr, S_IWUSR, NULL, store_sync_ddr);
+
+static const struct attribute *uio_sysfs_attrs[] = {
+	&dev_attr_sync_ddr.attr,
+	NULL
+};
+
+static int uio_sysfs_init(struct platform_device *pdev) {
+	int error;
+	error = sysfs_create_files(&pdev->dev.kobj, uio_sysfs_attrs);
+	if (error) {
+		dev_err(&pdev->dev, "Failed to create sysfs entries");
+	}
+	return error;
+}
+
+static void uio_sysfs_cleanup(struct platform_device *pdev) {
+	sysfs_remove_files(&pdev->dev.kobj, uio_sysfs_attrs);
+}
+
 static irqreturn_t pruss_handler(int irq, struct uio_info *info)
 {
 	struct uio_pruss_dev *gdev = info->priv;
@@ -97,6 +129,8 @@ static void pruss_cleanup(struct platform_device *dev,
 	int cnt;
 	struct uio_info *p = gdev->info;
 
+	uio_sysfs_cleanup(dev);
+
 	for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) {
 		uio_unregister_device(p);
 		kfree(p->name);
@@ -106,10 +140,12 @@ static void pruss_cleanup(struct platform_device *dev,
 		dma_free_coherent(&dev->dev, extram_pool_sz, gdev->ddr_vaddr,
 			gdev->ddr_paddr);
 	}
+#ifdef CONFIG_ARCH_DAVINCI_DA850
 	if (gdev->sram_vaddr)
 		gen_pool_free(gdev->sram_pool,
 			      gdev->sram_vaddr,
 			      sram_pool_sz);
+#endif
 	kfree(gdev->info);
 	clk_put(gdev->pruss_clk);
 	kfree(gdev);
@@ -120,8 +156,14 @@ static int pruss_probe(struct platform_device *dev)
 	struct uio_info *p;
 	struct uio_pruss_dev *gdev;
 	struct resource *regs_prussio;
+	struct resource res;
 	int ret = -ENODEV, cnt = 0, len;
 	struct uio_pruss_pdata *pdata = dev->dev.platform_data;
+	struct pinctrl *pinctrl;
+
+	int count;
+	struct device_node *child;
+	const char *pin_name;
 
 	gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL);
 	if (!gdev)
@@ -132,6 +174,7 @@ static int pruss_probe(struct platform_device *dev)
 		kfree(gdev);
 		return -ENOMEM;
 	}
+#ifdef CONFIG_ARCH_DAVINCI_DA850
 	/* Power on PRU in case its not done as part of boot-loader */
 	gdev->pruss_clk = clk_get(&dev->dev, "pruss");
 	if (IS_ERR(gdev->pruss_clk)) {
@@ -143,6 +186,57 @@ static int pruss_probe(struct platform_device *dev)
 	} else {
 		clk_enable(gdev->pruss_clk);
 	}
+#endif
+
+	if (dev->dev.of_node) {
+		pm_runtime_enable(&dev->dev);
+		ret = pm_runtime_get_sync(&dev->dev);
+		if (IS_ERR_VALUE(ret)) {
+			dev_err(&dev->dev, "pm_runtime_get_sync() failed\n");
+			return ret;
+		}
+
+		ret = of_address_to_resource(dev->dev.of_node, 0, &res);
+		if (IS_ERR_VALUE(ret)) {
+			dev_err(&dev->dev, "failed to parse DT reg\n");
+			return ret;
+		}
+		regs_prussio = &res;
+	}
+
+	pinctrl = devm_pinctrl_get_select_default(&dev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&dev->dev,
+			"pins are not configured from the driver\n");
+
+	// Run through all children. They have lables for easy reference.
+	for_each_child_of_node(dev->dev.of_node, child) {
+		enum of_gpio_flags flags;
+		unsigned gpio;
+
+		count = of_gpio_count(child);
+
+		ret = of_property_count_strings(child, "pin-names");
+		if (ret < 0) {
+			dev_err(&dev->dev, "Failed to get pin-names\n");
+			continue;
+		}
+		if(count != ret){
+			dev_err(&dev->dev, "The number of gpios (%d) does not match"\
+				" the number of pin names (%d)\n", count, ret);
+			continue;
+		}
+
+		dev_dbg(&dev->dev, "Child has %u gpios\n", count);
+		for(cnt=0; cnt<count; cnt++){
+			ret = of_property_read_string_index(child,
+				"pin-names", cnt, &pin_name);
+			if (ret != 0)
+				dev_err(&dev->dev, "Error on pin-name #%d\n", cnt);
+			gpio = of_get_gpio_flags(child, cnt, &flags);
+			ret = devm_gpio_request_one(&dev->dev, gpio, flags, pin_name);
+		}
+	}
 
 	regs_prussio = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	if (!regs_prussio) {
@@ -155,14 +249,16 @@ static int pruss_probe(struct platform_device *dev)
 		goto out_free;
 	}
 
-	if (pdata->sram_pool) {
+	if (pdata && pdata->sram_pool) {
 		gdev->sram_pool = pdata->sram_pool;
+#ifdef CONFIG_ARCH_DAVINCI_DA850
 		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;
 		}
+#endif
 		gdev->sram_paddr =
 			gen_pool_virt_to_phys(gdev->sram_pool,
 					      gdev->sram_vaddr);
@@ -182,7 +278,17 @@ static int pruss_probe(struct platform_device *dev)
 		goto out_free;
 	}
 
-	gdev->pintc_base = pdata->pintc_base;
+	if (dev->dev.of_node) {
+		ret = of_property_read_u32(dev->dev.of_node,
+					   "ti,pintc-offset",
+					   &gdev->pintc_base);
+		if (ret < 0) {
+			dev_err(&dev->dev,
+				"Can't parse ti,pintc-offset property\n");
+			goto out_free;
+		}
+	} else
+		gdev->pintc_base = pdata->pintc_base;
 	gdev->hostirq_start = platform_get_irq(dev, 0);
 
 	for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) {
@@ -190,6 +296,7 @@ static int pruss_probe(struct platform_device *dev)
 		p->mem[0].size = resource_size(regs_prussio);
 		p->mem[0].memtype = UIO_MEM_PHYS;
 
+#ifdef CONFIG_ARCH_DAVINCI_DA850
 		p->mem[1].addr = gdev->sram_paddr;
 		p->mem[1].size = sram_pool_sz;
 		p->mem[1].memtype = UIO_MEM_PHYS;
@@ -197,6 +304,11 @@ static int pruss_probe(struct platform_device *dev)
 		p->mem[2].addr = gdev->ddr_paddr;
 		p->mem[2].size = extram_pool_sz;
 		p->mem[2].memtype = UIO_MEM_PHYS;
+#else
+		p->mem[1].addr = gdev->ddr_paddr;
+		p->mem[1].size = extram_pool_sz;
+		p->mem[1].memtype = UIO_MEM_PHYS;
+#endif
 
 		p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt);
 		p->version = DRV_VERSION;
@@ -211,6 +323,9 @@ static int pruss_probe(struct platform_device *dev)
 			goto out_free;
 	}
 
+	if (uio_sysfs_init(dev))
+		goto out_free;
+
 	platform_set_drvdata(dev, gdev);
 	return 0;
 
@@ -228,12 +343,20 @@ static int pruss_remove(struct platform_device *dev)
 	return 0;
 }
 
+static const struct of_device_id pruss_dt_ids[] = {
+	{ .compatible = "ti,pruss-v1", .data = NULL, },
+	{ .compatible = "ti,pruss-v2", .data = NULL, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pruss_dt_ids);
+
 static struct platform_driver pruss_driver = {
 	.probe = pruss_probe,
 	.remove = pruss_remove,
 	.driver = {
 		   .name = DRV_NAME,
 		   .owner = THIS_MODULE,
+		   .of_match_table = pruss_dt_ids,
 		   },
 };
 
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 23a0b7f..de6e5ce 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -11,6 +11,7 @@ config USB_MUSB_HDRC
 	select NOP_USB_XCEIV if (SOC_TI81XX || SOC_AM33XX)
 	select TWL4030_USB if MACH_OMAP_3430SDP
 	select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
+	select OMAP_CONTROL_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
 	select USB_OTG_UTILS
 	help
 	  Say Y here if your system has a dual role high speed USB
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 60b41cc..4afa92a 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -1955,11 +1955,43 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 		musb_write_ulpi_buscontrol(musb->mregs, busctl);
 	}
 
-	MUSB_DEV_MODE(musb);
-	musb->xceiv->otg->default_a = 0;
-	musb->xceiv->state = OTG_STATE_B_IDLE;
+	dev_info(dev, "*** mode=%d\n", plat->mode);
+	dev_info(dev, "*** power=%d\n", plat->power);
 
-	status = musb_gadget_setup(musb);
+	/* For the host-only role, we can activate right away.
+	 * (We expect the ID pin to be forcibly grounded!!)
+	 * Otherwise, wait till the gadget driver hooks up.
+	 */
+	if (plat->mode == MUSB_HOST) {	/* host mode */
+
+		del_timer(&musb->otg_timer);
+
+		MUSB_HST_MODE(musb);
+		musb->xceiv->otg->default_a = 1;
+		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+
+		status = usb_add_hcd(hcd, 0, 0);
+
+		hcd->self.uses_pio_for_control = 1;
+		dev_dbg(musb->controller, "%s mode, status %d, devctl %02x %c\n",
+			"HOST", status,
+			musb_readb(musb->mregs, MUSB_DEVCTL),
+			(musb_readb(musb->mregs, MUSB_DEVCTL)
+				& MUSB_DEVCTL_BDEVICE
+				? 'B' : 'A'));
+
+	} else {
+		MUSB_DEV_MODE(musb);
+		musb->xceiv->otg->default_a = 0;
+		musb->xceiv->state = OTG_STATE_B_IDLE;
+
+		status = musb_gadget_setup(musb);
+
+		dev_dbg(musb->controller, "%s mode, status %d, dev%02x\n",
+			plat->mode == MUSB_OTG ? "OTG" : "PERIPHERAL",
+			status,
+			musb_readb(musb->mregs, MUSB_DEVCTL));
+	}
 
 	if (status < 0)
 		goto fail3;
@@ -1982,7 +2014,10 @@ fail5:
 	musb_exit_debugfs(musb);
 
 fail4:
-	musb_gadget_cleanup(musb);
+	if (plat->mode == MUSB_HOST)
+		usb_remove_hcd(hcd);
+	else
+		musb_gadget_cleanup(musb);
 
 fail3:
 	pm_runtime_put_sync(musb->controller);
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 341a4b5..c9946b9 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -230,8 +230,14 @@ static void otg_timer(unsigned long _musb)
 	spin_lock_irqsave(&musb->lock, flags);
 	switch (musb->xceiv->state) {
 	case OTG_STATE_A_WAIT_BCON:
-		devctl &= ~MUSB_DEVCTL_SESSION;
-		dsps_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+		/*
+		 * We need to avoid stopping the session in host mode,
+		 * otherwise we don't see any newly connected devices
+		 */
+		if (!is_host_active(musb)) {
+			devctl &= ~MUSB_DEVCTL_SESSION;
+			dsps_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+		}
 
 		devctl = dsps_readb(musb->mregs, MUSB_DEVCTL);
 		if (devctl & MUSB_DEVCTL_BDEVICE) {
@@ -415,19 +421,32 @@ 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;
 
+#if 1
 	/* NOP driver needs change if supporting dual instance */
-	usb_nop_xceiv_register();
+	if(!pdev->id) {
+		usb_nop_xceiv_register();
+	}
 	musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
-	if (IS_ERR_OR_NULL(musb->xceiv))
+#else
+	/* Get the NOP PHY */
+	sprintf(name, "usb%d-phy", pdev->id);
+	musb->xceiv = devm_usb_get_phy_by_phandle(&parent_pdev->dev, name);
+#endif
+	if (IS_ERR_OR_NULL(musb->xceiv)) {
+		dev_err(dev, "%s:%d %s: FAIL\n", __FILE__, __LINE__, __func__);
 		return -EPROBE_DEFER;
+	}
 
 	/* Returns zero if e.g. not clocked */
 	rev = dsps_readl(reg_base, wrp->revision);
 	if (!rev) {
+		dev_err(dev, "%s:%d %s: FAIL\n", __FILE__, __LINE__, __func__);
 		status = -ENODEV;
 		goto err0;
 	}
 
+	dev_info(dev, "pdev->id = %d\n", pdev->id);
+
 	setup_timer(&glue->timer[pdev->id], otg_timer, (unsigned long) musb);
 
 	/* Reset the musb */
@@ -446,10 +465,14 @@ static int dsps_musb_init(struct musb *musb)
 	/* clear level interrupt */
 	dsps_writel(reg_base, wrp->eoi, 0);
 
+	dev_info(dev, "%s:%d %s: OK\n", __FILE__, __LINE__, __func__);
+
 	return 0;
 err0:
 	usb_put_phy(musb->xceiv);
-	usb_nop_xceiv_unregister();
+	if(!pdev->id) {
+		usb_nop_xceiv_unregister();
+	}
 	return status;
 }
 
@@ -466,7 +489,9 @@ static int dsps_musb_exit(struct musb *musb)
 
 	/* NOP driver needs change if supporting dual instance */
 	usb_put_phy(musb->xceiv);
-	usb_nop_xceiv_unregister();
+	if(!pdev->id) {
+		usb_nop_xceiv_unregister();
+	}
 
 	return 0;
 }
@@ -761,9 +786,41 @@ static const struct platform_device_id musb_dsps_id_table[] = {
 MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);
 
 #ifdef CONFIG_OF
+
+static const struct dsps_musb_wrapper am33xx_driver_data = {
+	.revision		= 0x00,
+	.control		= 0x14,
+	.status			= 0x18,
+	.eoi			= 0x24,
+	.epintr_set		= 0x38,
+	.epintr_clear		= 0x40,
+	.epintr_status		= 0x30,
+	.coreintr_set		= 0x3c,
+	.coreintr_clear		= 0x44,
+	.coreintr_status	= 0x34,
+	.phy_utmi		= 0xe0,
+	.mode			= 0xe8,
+	.reset			= 0,
+	.otg_disable		= 21,
+	.iddig			= 8,
+	.usb_shift		= 0,
+	.usb_mask		= 0x1ff,
+	.usb_bitmap		= (0x1ff << 0),
+	.drvvbus		= 8,
+	.txep_shift		= 0,
+	.txep_mask		= 0xffff,
+	.txep_bitmap		= (0xffff << 0),
+	.rxep_shift		= 16,
+	.rxep_mask		= 0xfffe,
+	.rxep_bitmap		= (0xfffe << 16),
+	.musb_core_offset	= 0x400,
+	.poll_seconds		= 2,
+	.instances		= 2,
+};
+
 static const struct of_device_id musb_dsps_of_match[] = {
 	{ .compatible = "ti,musb-am33xx",
-		.data = (void *) &ti81xx_driver_data, },
+		.data = (void *) &am33xx_driver_data, },
 	{  },
 };
 MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index e9f0fd9..86442a2 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -2431,12 +2431,15 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
 		break;
 	}
 
+#if 0
 	if (musb->is_active) {
 		WARNING("trying to suspend as %s while active\n",
 				otg_state_string(musb->xceiv->state));
 		return -EBUSY;
-	} else
-		return 0;
+	}
+#endif
+
+	return 0;
 }
 
 static int musb_bus_resume(struct usb_hcd *hcd)
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index d7772856..05ab371 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -37,6 +37,7 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/usb/musb-omap.h>
+#include <linux/usb/omap_control_usb.h>
 
 #include "musb_core.h"
 #include "omap2430.h"
@@ -46,7 +47,7 @@ struct omap2430_glue {
 	struct platform_device	*musb;
 	enum omap_musb_vbus_id_status status;
 	struct work_struct	omap_musb_mailbox_work;
-	u32 __iomem		*control_otghs;
+	struct device		*control_otghs;
 };
 #define glue_to_musb(g)		platform_get_drvdata(g->musb)
 
@@ -54,26 +55,6 @@ struct omap2430_glue		*_glue;
 
 static struct timer_list musb_idle_timer;
 
-/**
- * omap4_usb_phy_mailbox - write to usb otg mailbox
- * @glue: struct omap2430_glue *
- * @val: the value to be written to the mailbox
- *
- * On detection of a device (ID pin is grounded), this API should be called
- * to set AVALID, VBUSVALID and ID pin is grounded.
- *
- * When OMAP is connected to a host (OMAP in device mode), this API
- * is called to set AVALID, VBUSVALID and ID pin in high impedance.
- *
- * XXX: This function will be removed once we have a seperate driver for
- * control module
- */
-static void omap4_usb_phy_mailbox(struct omap2430_glue *glue, u32 val)
-{
-	if (glue->control_otghs)
-		writel(val, glue->control_otghs);
-}
-
 static void musb_do_idle(unsigned long _musb)
 {
 	struct musb	*musb = (void *)_musb;
@@ -269,7 +250,6 @@ EXPORT_SYMBOL_GPL(omap_musb_mailbox);
 
 static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 {
-	u32 val;
 	struct musb *musb = glue_to_musb(glue);
 	struct device *dev = musb->controller;
 	struct musb_hdrc_platform_data *pdata = dev->platform_data;
@@ -285,8 +265,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 		musb->xceiv->last_event = USB_EVENT_ID;
 		if (musb->gadget_driver) {
 			pm_runtime_get_sync(dev);
-			val = AVALID | VBUSVALID;
-			omap4_usb_phy_mailbox(glue, val);
+			if (!IS_ERR(glue->control_otghs))
+				omap_control_usb_host_mode(glue->control_otghs);
 			omap2430_musb_set_vbus(musb, 1);
 		}
 		break;
@@ -299,8 +279,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 		musb->xceiv->last_event = USB_EVENT_VBUS;
 		if (musb->gadget_driver)
 			pm_runtime_get_sync(dev);
-		val = IDDIG | AVALID | VBUSVALID;
-		omap4_usb_phy_mailbox(glue, val);
+		if (!IS_ERR(glue->control_otghs))
+			omap_control_usb_device_mode(glue->control_otghs);
 		break;
 
 	case OMAP_MUSB_ID_FLOAT:
@@ -317,8 +297,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 			if (musb->xceiv->otg->set_vbus)
 				otg_set_vbus(musb->xceiv->otg, 0);
 		}
-		val = SESSEND | IDDIG;
-		omap4_usb_phy_mailbox(glue, val);
+		if (!IS_ERR(glue->control_otghs))
+			omap_control_usb_set_sessionend(glue->control_otghs);
 		break;
 	default:
 		dev_dbg(dev, "ID float\n");
@@ -366,7 +346,12 @@ static int omap2430_musb_init(struct musb *musb)
 	 * up through ULPI.  TWL4030-family PMICs include one,
 	 * which needs a driver, drivers aren't always needed.
 	 */
-	musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+	if (dev->parent->of_node)
+		musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent,
+		    "usb_phy", 0);
+	else
+		musb->xceiv = devm_usb_get_phy_dev(dev, 0);
+
 	if (IS_ERR_OR_NULL(musb->xceiv)) {
 		pr_err("HS USB OTG: no transceiver configured\n");
 		return -EPROBE_DEFER;
@@ -415,7 +400,6 @@ err1:
 static void omap2430_musb_enable(struct musb *musb)
 {
 	u8		devctl;
-	u32		val;
 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 	struct device *dev = musb->controller;
 	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
@@ -425,8 +409,8 @@ static void omap2430_musb_enable(struct musb *musb)
 	switch (glue->status) {
 
 	case OMAP_MUSB_ID_GROUND:
-		val = AVALID | VBUSVALID;
-		omap4_usb_phy_mailbox(glue, val);
+		if (!IS_ERR(glue->control_otghs))
+			omap_control_usb_host_mode(glue->control_otghs);
 		if (data->interface_type != MUSB_INTERFACE_UTMI)
 			break;
 		devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
@@ -445,8 +429,8 @@ static void omap2430_musb_enable(struct musb *musb)
 		break;
 
 	case OMAP_MUSB_VBUS_VALID:
-		val = IDDIG | AVALID | VBUSVALID;
-		omap4_usb_phy_mailbox(glue, val);
+		if (!IS_ERR(glue->control_otghs))
+			omap_control_usb_device_mode(glue->control_otghs);
 		break;
 
 	default:
@@ -456,13 +440,12 @@ static void omap2430_musb_enable(struct musb *musb)
 
 static void omap2430_musb_disable(struct musb *musb)
 {
-	u32 val;
 	struct device *dev = musb->controller;
 	struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 
 	if (glue->status != OMAP_MUSB_UNKNOWN) {
-		val = SESSEND | IDDIG;
-		omap4_usb_phy_mailbox(glue, val);
+		if (!IS_ERR(glue->control_otghs))
+			omap_control_usb_set_sessionend(glue->control_otghs);
 	}
 }
 
@@ -523,9 +506,6 @@ static int omap2430_probe(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 
-	glue->control_otghs = devm_request_and_ioremap(&pdev->dev, res);
-	if (glue->control_otghs == NULL)
-		dev_dbg(&pdev->dev, "Failed to obtain control memory\n");
 
 	if (np) {
 		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
@@ -558,11 +538,22 @@ static int omap2430_probe(struct platform_device *pdev)
 		of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits);
 		of_property_read_u32(np, "power", (u32 *)&pdata->power);
 		config->multipoint = of_property_read_bool(np, "multipoint");
+		pdata->has_mailbox = of_property_read_bool(np,
+		    "ti,has_mailbox");
 
 		pdata->board_data	= data;
 		pdata->config		= config;
 	}
 
+	if (pdata->has_mailbox) {
+		glue->control_otghs = get_omap_control_dev();
+		if (IS_ERR(glue->control_otghs)) {
+			dev_vdbg(&pdev->dev, "Failed to get control device\n");
+			return -ENODEV;
+		}
+	} else {
+		glue->control_otghs = ERR_PTR(-ENODEV);
+	}
 	pdata->platform_ops		= &omap2430_ops;
 
 	platform_set_drvdata(pdev, glue);
diff --git a/drivers/usb/musb/omap2430.h b/drivers/usb/musb/omap2430.h
index 8ef6566..1b5e83a 100644
--- a/drivers/usb/musb/omap2430.h
+++ b/drivers/usb/musb/omap2430.h
@@ -49,13 +49,4 @@
 #define OTG_FORCESTDBY		0x414
 #	define	ENABLEFORCE		(1 << 0)
 
-/*
- * Control Module bit definitions
- * XXX: Will be removed once we have a driver for control module.
- */
-#define	AVALID				BIT(0)
-#define	BVALID				BIT(1)
-#define	VBUSVALID			BIT(2)
-#define	SESSEND				BIT(3)
-#define	IDDIG				BIT(4)
 #endif	/* __MUSB_OMAP243X_H__ */
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
index a30c041..67daf8c 100644
--- a/drivers/usb/otg/otg.c
+++ b/drivers/usb/otg/otg.c
@@ -13,11 +13,14 @@
 #include <linux/export.h>
 #include <linux/err.h>
 #include <linux/device.h>
+#include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #include <linux/usb/otg.h>
 
 static LIST_HEAD(phy_list);
+static LIST_HEAD(phy_bind_list);
 static DEFINE_SPINLOCK(phy_lock);
 
 static struct usb_phy *__usb_find_phy(struct list_head *list,
@@ -35,6 +38,34 @@ static struct usb_phy *__usb_find_phy(struct list_head *list,
 	return ERR_PTR(-ENODEV);
 }
 
+static struct usb_phy *__usb_find_phy_dev(struct device *dev,
+	struct list_head *list, u8 index)
+{
+	struct usb_phy_bind *phy_bind = NULL;
+
+	list_for_each_entry(phy_bind, list, list) {
+		if (!(strcmp(phy_bind->dev_name, dev_name(dev))) &&
+				phy_bind->index == index)
+			return phy_bind->phy;
+	}
+
+	return ERR_PTR(-ENODEV);
+}
+
+static struct usb_phy *__of_usb_find_phy(struct device_node *node)
+{
+	struct usb_phy  *phy;
+
+	list_for_each_entry(phy, &phy_list, head) {
+		if (node != phy->dev->of_node)
+			continue;
+
+		return phy;
+	}
+
+	return ERR_PTR(-ENODEV);
+}
+
 static void devm_usb_phy_release(struct device *dev, void *res)
 {
 	struct usb_phy *phy = *(struct usb_phy **)res;
@@ -110,6 +141,130 @@ err0:
 }
 EXPORT_SYMBOL(usb_get_phy);
 
+ /**
+ * devm_usb_get_phy_by_phandle - find the USB PHY by phandle
+ * @dev - device that requests this phy
+ * @phandle - name of the property holding the phy phandle value
+ * @index - the index of the phy
+ *
+ * Returns the phy driver associated with the given phandle value,
+ * after getting a refcount to it, -ENODEV if there is no such phy or
+ * -EPROBE_DEFER if there is a phandle to the phy, but the device is
+ * not yet loaded. While at that, it also associates the device with
+ * the phy using devres. On driver detach, release function is invoked
+ * on the devres data, then, devres data is freed.
+ *
+ * For use by USB host and peripheral drivers.
+ */
+struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
+	const char *phandle, u8 index)
+{
+	struct usb_phy	*phy = NULL, **ptr;
+	unsigned long	flags;
+	struct device_node *node;
+
+	if (!dev->of_node) {
+		dev_dbg(dev, "device does not have a device node entry\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	node = of_parse_phandle(dev->of_node, phandle, index);
+	if (!node) {
+		dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
+			dev->of_node->full_name);
+		return ERR_PTR(-ENODEV);
+	}
+
+	ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr) {
+		dev_dbg(dev, "failed to allocate memory for devres\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	spin_lock_irqsave(&phy_lock, flags);
+
+	phy = __of_usb_find_phy(node);
+	if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
+		phy = ERR_PTR(-EPROBE_DEFER);
+		devres_free(ptr);
+		goto err0;
+	}
+
+	*ptr = phy;
+	devres_add(dev, ptr);
+
+	get_device(phy->dev);
+
+err0:
+	spin_unlock_irqrestore(&phy_lock, flags);
+
+	return phy;
+}
+EXPORT_SYMBOL(devm_usb_get_phy_by_phandle);
+
+/**
+ * usb_get_phy_dev - find the USB PHY
+ * @dev - device that requests this phy
+ * @index - the index of the phy
+ *
+ * Returns the phy driver, after getting a refcount to it; or
+ * -ENODEV if there is no such phy.  The caller is responsible for
+ * calling usb_put_phy() to release that count.
+ *
+ * For use by USB host and peripheral drivers.
+ */
+struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
+{
+	struct usb_phy	*phy = NULL;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&phy_lock, flags);
+
+	phy = __usb_find_phy_dev(dev, &phy_bind_list, index);
+	if (IS_ERR(phy)) {
+		pr_err("unable to find transceiver\n");
+		goto err0;
+	}
+
+	get_device(phy->dev);
+
+err0:
+	spin_unlock_irqrestore(&phy_lock, flags);
+
+	return phy;
+}
+EXPORT_SYMBOL(usb_get_phy_dev);
+
+/**
+ * devm_usb_get_phy_dev - find the USB PHY using device ptr and index
+ * @dev - device that requests this phy
+ * @index - the index of the phy
+ *
+ * Gets the phy using usb_get_phy_dev(), and associates a device with it using
+ * devres. On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.
+ *
+ * For use by USB host and peripheral drivers.
+ */
+struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
+{
+	struct usb_phy **ptr, *phy;
+
+	ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return NULL;
+
+	phy = usb_get_phy_dev(dev, index);
+	if (!IS_ERR(phy)) {
+		*ptr = phy;
+		devres_add(dev, ptr);
+	} else
+		devres_free(ptr);
+
+	return phy;
+}
+EXPORT_SYMBOL(devm_usb_get_phy_dev);
+
 /**
  * devm_usb_put_phy - release the USB PHY
  * @dev - device that wants to release this phy
@@ -185,6 +340,36 @@ out:
 EXPORT_SYMBOL(usb_add_phy);
 
 /**
+ * usb_add_phy_dev - declare the USB PHY
+ * @x: the USB phy to be used; or NULL
+ *
+ * This call is exclusively for use by phy drivers, which
+ * coordinate the activities of drivers for host and peripheral
+ * controllers, and in some cases for VBUS current regulation.
+ */
+int usb_add_phy_dev(struct usb_phy *x)
+{
+	struct usb_phy_bind *phy_bind;
+	unsigned long flags;
+
+	if (!x->dev) {
+		dev_err(x->dev, "no device provided for PHY\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&phy_lock, flags);
+	list_for_each_entry(phy_bind, &phy_bind_list, list)
+		if (!(strcmp(phy_bind->phy_dev_name, dev_name(x->dev))))
+			phy_bind->phy = x;
+
+	list_add_tail(&x->head, &phy_list);
+
+	spin_unlock_irqrestore(&phy_lock, flags);
+	return 0;
+}
+EXPORT_SYMBOL(usb_add_phy_dev);
+
+/**
  * usb_remove_phy - remove the OTG PHY
  * @x: the USB OTG PHY to be removed;
  *
@@ -193,14 +378,55 @@ EXPORT_SYMBOL(usb_add_phy);
 void usb_remove_phy(struct usb_phy *x)
 {
 	unsigned long	flags;
+	struct usb_phy_bind *phy_bind;
 
 	spin_lock_irqsave(&phy_lock, flags);
-	if (x)
+	if (x) {
+		list_for_each_entry(phy_bind, &phy_bind_list, list)
+			if (phy_bind->phy == x)
+				phy_bind->phy = NULL;
 		list_del(&x->head);
+	}
 	spin_unlock_irqrestore(&phy_lock, flags);
 }
 EXPORT_SYMBOL(usb_remove_phy);
 
+/**
+ * usb_bind_phy - bind the phy and the controller that uses the phy
+ * @dev_name: the device name of the device that will bind to the phy
+ * @index: index to specify the port number
+ * @phy_dev_name: the device name of the phy
+ *
+ * Fills the phy_bind structure with the dev_name and phy_dev_name. This will
+ * be used when the phy driver registers the phy and when the controller
+ * requests this phy.
+ *
+ * To be used by platform specific initialization code.
+ */
+struct usb_phy_bind __init *usb_bind_phy(const char *dev_name, u8 index,
+				const char *phy_dev_name)
+{
+	struct usb_phy_bind *phy_bind;
+	unsigned long flags;
+
+	phy_bind = kzalloc(sizeof(*phy_bind), GFP_KERNEL);
+	if (!phy_bind) {
+		pr_err("phy_bind(): No memory for phy_bind");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	phy_bind->dev_name = dev_name;
+	phy_bind->phy_dev_name = phy_dev_name;
+	phy_bind->index = index;
+
+	spin_lock_irqsave(&phy_lock, flags);
+	list_add_tail(&phy_bind->list, &phy_bind_list);
+	spin_unlock_irqrestore(&phy_lock, flags);
+
+	return phy_bind;
+}
+EXPORT_SYMBOL_GPL(usb_bind_phy);
+
 const char *otg_state_string(enum usb_otg_state state)
 {
 	switch (state) {
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 0a70193..a994715 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -610,6 +610,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
 	twl->phy.dev		= twl->dev;
 	twl->phy.label		= "twl4030";
 	twl->phy.otg		= otg;
+	twl->phy.type		= USB_PHY_TYPE_USB2;
 	twl->phy.set_suspend	= twl4030_set_suspend;
 
 	otg->phy		= &twl->phy;
@@ -624,7 +625,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "ldo init failed\n");
 		return err;
 	}
-	usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
+	usb_add_phy_dev(&twl->phy);
 
 	platform_set_drvdata(pdev, twl);
 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 5de6e7f..16bdaca 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -8,12 +8,22 @@ config OMAP_USB2
 	tristate "OMAP USB2 PHY Driver"
 	depends on ARCH_OMAP2PLUS
 	select USB_OTG_UTILS
+	select OMAP_CONTROL_USB
 	help
 	  Enable this to support the transceiver that is part of SOC. This
 	  driver takes care of all the PHY functionality apart from comparator.
 	  The USB OTG controller communicates with the comparator using this
 	  driver.
 
+config OMAP_CONTROL_USB
+	tristate "OMAP CONTROL USB Driver"
+	depends on ARCH_OMAP2PLUS
+	help
+	  Enable this to add support for the USB part present in the control
+	  module. This driver has API to power on the PHY and to write to the
+	  mailbox. The mailbox is present only in omap4 and the register to
+	  power on the PHY is present in omap4 and omap5.
+
 config USB_ISP1301
 	tristate "NXP ISP1301 USB transceiver support"
 	depends on USB || USB_GADGET
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index 1a579a8..0dea4d2 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -5,6 +5,7 @@
 ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
 
 obj-$(CONFIG_OMAP_USB2)			+= omap-usb2.o
+obj-$(CONFIG_OMAP_CONTROL_USB)		+= omap-control-usb.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
diff --git a/drivers/usb/phy/omap-control-usb.c b/drivers/usb/phy/omap-control-usb.c
new file mode 100644
index 0000000..bed41a9
--- /dev/null
+++ b/drivers/usb/phy/omap-control-usb.c
@@ -0,0 +1,204 @@
+/*
+ * omap-control-usb.c - The USB part of control module.
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/usb/omap_control_usb.h>
+
+static struct omap_control_usb *control_usb;
+
+/**
+ * get_omap_control_dev - returns the device pointer for this control device
+ *
+ * This API should be called to get the device pointer for this control
+ * module device. This device pointer should be passed to all other API's
+ * in this driver.
+ *
+ * To be used by PHY driver and glue driver
+ */
+struct device *get_omap_control_dev(void)
+{
+	if (!control_usb)
+		return ERR_PTR(-ENODEV);
+
+	return control_usb->dev;
+}
+EXPORT_SYMBOL_GPL(get_omap_control_dev);
+
+/**
+ * omap_control_usb_phy_power - power on/off the phy using control module reg
+ * @dev: the control module device
+ * @on: 0 or 1, based on powering on or off the PHY
+ */
+void omap_control_usb_phy_power(struct device *dev, int on)
+{
+	u32 val;
+	struct omap_control_usb	*control_usb = dev_get_drvdata(dev);
+
+	if (on) {
+		val = readl(control_usb->dev_conf);
+		if (val & PHY_PD)
+			writel(~PHY_PD, control_usb->dev_conf);
+	} else {
+		writel(PHY_PD, control_usb->dev_conf);
+	}
+}
+EXPORT_SYMBOL_GPL(omap_control_usb_phy_power);
+
+/**
+ * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded
+ * @dev: struct device *
+ *
+ * This is an API to write to the mailbox register to notify the usb core that
+ * a usb device has been connected.
+ */
+void omap_control_usb_host_mode(struct device *dev)
+{
+	u32 val;
+	struct omap_control_usb	*control_usb = dev_get_drvdata(dev);
+
+	val = AVALID | VBUSVALID;
+
+	writel(val, control_usb->otghs_control);
+}
+EXPORT_SYMBOL_GPL(omap_control_usb_host_mode);
+
+/**
+ * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high
+ * impedance
+ * @dev: struct device *
+ *
+ * This is an API to write to the mailbox register to notify the usb core that
+ * it has been connected to a usb host.
+ */
+void omap_control_usb_device_mode(struct device *dev)
+{
+	u32 val;
+	struct omap_control_usb	*control_usb = dev_get_drvdata(dev);
+
+	val = IDDIG | AVALID | VBUSVALID;
+
+	writel(val, control_usb->otghs_control);
+}
+EXPORT_SYMBOL_GPL(omap_control_usb_device_mode);
+
+/**
+ * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high
+ * impedance
+ * @dev: struct device *
+ *
+ * This is an API to write to the mailbox register to notify the usb core
+ * it's now in disconnected state.
+ */
+void omap_control_usb_set_sessionend(struct device *dev)
+{
+	u32 val;
+	struct omap_control_usb	*control_usb = dev_get_drvdata(dev);
+
+	val = SESSEND | IDDIG;
+
+	writel(val, control_usb->otghs_control);
+}
+EXPORT_SYMBOL_GPL(omap_control_usb_set_sessionend);
+
+static int omap_control_usb_probe(struct platform_device *pdev)
+{
+	struct resource	*res;
+	struct device_node *np = pdev->dev.of_node;
+	struct omap_control_usb_platform_data *pdata = pdev->dev.platform_data;
+
+	control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),
+	    GFP_KERNEL);
+	if (!control_usb) {
+		dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
+		return -ENOMEM;
+	}
+
+	if (np) {
+		control_usb->has_mailbox = of_property_read_bool(np,
+		    "ti,has_mailbox");
+	} else if (pdata) {
+		control_usb->has_mailbox = pdata->has_mailbox;
+	} else {
+		dev_err(&pdev->dev, "no pdata present\n");
+		return -EINVAL;
+	}
+
+	control_usb->dev	= &pdev->dev;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+	    "control_dev_conf");
+	control_usb->dev_conf = devm_request_and_ioremap(&pdev->dev, res);
+	if (control_usb->dev_conf == NULL) {
+		dev_err(&pdev->dev, "Failed to obtain io memory\n");
+		return -ENXIO;
+	}
+
+	if (control_usb->has_mailbox) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+		    "otghs_control");
+		control_usb->otghs_control = devm_request_and_ioremap(
+		    &pdev->dev, res);
+		if (control_usb->otghs_control == NULL) {
+			dev_err(&pdev->dev, "Failed to obtain io memory\n");
+			return -ENXIO;
+		}
+	}
+
+	dev_set_drvdata(control_usb->dev, control_usb);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id omap_control_usb_id_table[] = {
+	{ .compatible = "ti,omap-control-usb" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
+#endif
+
+static struct platform_driver omap_control_usb_driver = {
+	.probe		= omap_control_usb_probe,
+	.driver		= {
+		.name	= "omap-control-usb",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(omap_control_usb_id_table),
+	},
+};
+
+static int __init omap_control_usb_init(void)
+{
+	return platform_driver_register(&omap_control_usb_driver);
+}
+subsys_initcall(omap_control_usb_init);
+
+static void __exit omap_control_usb_exit(void)
+{
+	platform_driver_unregister(&omap_control_usb_driver);
+}
+module_exit(omap_control_usb_exit);
+
+MODULE_ALIAS("platform: omap_control_usb");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("OMAP CONTROL USB DRIVER");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c
index 26ae8f4..46c79c6 100644
--- a/drivers/usb/phy/omap-usb2.c
+++ b/drivers/usb/phy/omap-usb2.c
@@ -27,6 +27,7 @@
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
 #include <linux/delay.h>
+#include <linux/usb/omap_control_usb.h>
 
 /**
  * omap_usb2_set_comparator - links the comparator present in the sytem with
@@ -52,29 +53,6 @@ int omap_usb2_set_comparator(struct phy_companion *comparator)
 }
 EXPORT_SYMBOL_GPL(omap_usb2_set_comparator);
 
-/**
- * omap_usb_phy_power - power on/off the phy using control module reg
- * @phy: struct omap_usb *
- * @on: 0 or 1, based on powering on or off the PHY
- *
- * XXX: Remove this function once control module driver gets merged
- */
-static void omap_usb_phy_power(struct omap_usb *phy, int on)
-{
-	u32 val;
-
-	if (on) {
-		val = readl(phy->control_dev);
-		if (val & PHY_PD) {
-			writel(~PHY_PD, phy->control_dev);
-			/* XXX: add proper documentation for this delay */
-			mdelay(200);
-		}
-	} else {
-		writel(PHY_PD, phy->control_dev);
-	}
-}
-
 static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled)
 {
 	struct omap_usb *phy = phy_to_omapusb(otg->phy);
@@ -124,7 +102,7 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
 	struct omap_usb *phy = phy_to_omapusb(x);
 
 	if (suspend && !phy->is_suspended) {
-		omap_usb_phy_power(phy, 0);
+		omap_control_usb_phy_power(phy->control_dev, 0);
 		pm_runtime_put_sync(phy->dev);
 		phy->is_suspended = 1;
 	} else if (!suspend && phy->is_suspended) {
@@ -134,7 +112,7 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
 									ret);
 			return ret;
 		}
-		omap_usb_phy_power(phy, 1);
+		omap_control_usb_phy_power(phy->control_dev, 1);
 		phy->is_suspended = 0;
 	}
 
@@ -165,17 +143,18 @@ static int omap_usb2_probe(struct platform_device *pdev)
 	phy->phy.label		= "omap-usb2";
 	phy->phy.set_suspend	= omap_usb2_suspend;
 	phy->phy.otg		= otg;
+	phy->phy.type		= USB_PHY_TYPE_USB2;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 
-	phy->control_dev = devm_request_and_ioremap(&pdev->dev, res);
-	if (phy->control_dev == NULL) {
-		dev_err(&pdev->dev, "Failed to obtain io memory\n");
-		return -ENXIO;
+	phy->control_dev = get_omap_control_dev();
+	if (IS_ERR(phy->control_dev)) {
+		dev_dbg(&pdev->dev, "Failed to get control device\n");
+		return -ENODEV;
 	}
 
 	phy->is_suspended	= 1;
-	omap_usb_phy_power(phy, 0);
+	omap_control_usb_phy_power(phy->control_dev, 0);
 
 	otg->set_host		= omap_usb_set_host;
 	otg->set_peripheral	= omap_usb_set_peripheral;
@@ -190,7 +169,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
 	}
 	clk_prepare(phy->wkupclk);
 
-	usb_add_phy(&phy->phy, USB_PHY_TYPE_USB2);
+	usb_add_phy_dev(&phy->phy);
 
 	platform_set_drvdata(pdev, phy);
 
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index e7068c5..a0c757a 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -33,6 +33,30 @@ config VIDEO_OUTPUT_CONTROL
 	  This framework adds support for low-level control of the video 
 	  output switch.
 
+config DISPLAY_TIMING
+       bool
+
+config VIDEOMODE
+       bool
+
+config OF_DISPLAY_TIMING
+	bool "Enable device tree display timing support"
+	depends on OF
+	select DISPLAY_TIMING
+	help
+	  helper to parse display timings from the devicetree
+
+config OF_VIDEOMODE
+	bool "Enable device tree videomode support"
+	depends on OF
+	select VIDEOMODE
+	select OF_DISPLAY_TIMING
+	help
+	  helper to get videomodes from the devicetree
+
+config HDMI
+	bool
+
 menuconfig FB
 	tristate "Support for frame buffer devices"
 	---help---
@@ -2204,7 +2228,7 @@ config FB_SH7760
 
 config FB_DA8XX
 	tristate "DA8xx/OMAP-L1xx Framebuffer support"
-	depends on FB && ARCH_DAVINCI_DA8XX
+	depends on FB && (ARCH_DAVINCI_DA8XX || SOC_AM33XX)
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -2419,6 +2443,17 @@ config FB_PUV3_UNIGFX
 	  Choose this option if you want to use the Unigfx device as a
 	  framebuffer device. Without the support of PCI & AGP.
 
+config FB_ST7735
+	tristate "ST7735 framebuffer support"
+	depends on FB && SPI
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	select FB_DEFERRED_IO
+	help
+	  Framebuffer support for the ST7735 display controller in SPI mode.
+
 source "drivers/video/omap/Kconfig"
 source "drivers/video/omap2/Kconfig"
 source "drivers/video/exynos/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 768a137..28bfbca 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -5,6 +5,7 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_VGASTATE)            += vgastate.o
+obj-$(CONFIG_HDMI)                += hdmi.o
 obj-y                             += fb_notify.o
 obj-$(CONFIG_FB)                  += fb.o
 fb-y                              := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
@@ -146,6 +147,7 @@ obj-$(CONFIG_FB_MSM)              += msm/
 obj-$(CONFIG_FB_NUC900)           += nuc900fb.o
 obj-$(CONFIG_FB_JZ4740)		  += jz4740_fb.o
 obj-$(CONFIG_FB_PUV3_UNIGFX)      += fb-puv3.o
+obj-$(CONFIG_FB_ST7735)		  += st7735fb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
@@ -168,3 +170,7 @@ obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
 
 #video output switch sysfs driver
 obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
+obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o
+obj-$(CONFIG_OF_DISPLAY_TIMING) += of_display_timing.o
+obj-$(CONFIG_VIDEOMODE) += videomode.o
+obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 765a945..50c9e35 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -390,6 +390,14 @@ config BACKLIGHT_TPS65217
 	  If you have a Texas Instruments TPS65217 say Y to enable the
 	  backlight driver.
 
+config BACKLIGHT_TLC59108
+	tristate "TLC59108 LCD Backlight Driver"
+	depends on I2C && BACKLIGHT_CLASS_DEVICE
+	default n
+	help
+	  If you have an LCD Panel with backlight control via TLC59108,
+	  say Y to enable its LCD control driver.
+
 endif # BACKLIGHT_CLASS_DEVICE
 
 endif # BACKLIGHT_LCD_SUPPORT
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index e7ce729..2f4711d 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -43,5 +43,6 @@ obj-$(CONFIG_BACKLIGHT_ADP8870)	+= adp8870_bl.o
 obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)	+= pcf50633-backlight.o
 obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
+obj-$(CONFIG_BACKLIGHT_TLC59108)	+= tlc59108.o
 obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
 obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 069983c..f3b6194 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -20,6 +20,8 @@
 #include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/slab.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/err.h>
 
 struct pwm_bl_data {
 	struct pwm_device	*pwm;
@@ -143,6 +145,11 @@ static int pwm_backlight_parse_dt(struct device *dev,
 
 		data->dft_brightness = value;
 		data->max_brightness--;
+
+		ret = of_property_read_u32(node, "low_threshold_brightness",
+					   &value);
+		if (!ret)
+			data->lth_brightness = value;
 	}
 
 	/*
@@ -175,9 +182,14 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 	struct backlight_properties props;
 	struct backlight_device *bl;
 	struct pwm_bl_data *pb;
+	struct pinctrl *pinctrl;
 	unsigned int max;
 	int ret;
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev, "unable to select pin group\n");
+
 	if (!data) {
 		ret = pwm_backlight_parse_dt(&pdev->dev, &defdata);
 		if (ret < 0) {
diff --git a/drivers/video/backlight/tlc59108.c b/drivers/video/backlight/tlc59108.c
new file mode 100644
index 0000000..40a21e7
--- /dev/null
+++ b/drivers/video/backlight/tlc59108.c
@@ -0,0 +1,176 @@
+/*
+ * ti81xxhdmi_tlc59108.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Senthil Natarajan
+ *
+ * tlc59108 HDMI 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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/>.
+ * History:
+ *
+ * Senthil Natarajan<senthil.n@ti.com> July 2011 I2C driver for tlc59108
+ *						 backlight control
+ */
+
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+
+#define TLC59108_MODE1   0x00
+#define TLC59108_MODE2   0x01
+#define TLC59108_PWM0 0x02
+#define TLC59108_PWM1 0x03
+#define TLC59108_PWM2 0x04
+#define TLC59108_PWM3 0x05
+#define TLC59108_PWM4 0x06
+#define TLC59108_PWM5 0x07
+#define TLC59108_PWM6 0x08
+#define TLC59108_PWM7 0x09
+#define TLC59108_LEDOUT0 0x0c
+#define TLC59108_LEDOUT1 0x0d
+#define TLC59108_MAX_BRIGHTNESS 0xFF
+
+struct tlc59108_bl {
+	struct i2c_client *client;
+	struct backlight_device *bl;
+};
+
+static void tlc59108_bl_set_backlight(struct tlc59108_bl *data, int brightness)
+{
+	/* Set Backlight Duty Cycle*/
+	i2c_smbus_write_byte_data(data->client, TLC59108_PWM2,
+				  0xff - brightness );
+}
+
+static int tlc59108_bl_get_brightness(struct backlight_device *dev)
+{
+	struct backlight_properties *props = &dev->props;
+
+	return props->brightness;
+}
+
+static int tlc59108_bl_update_status(struct backlight_device *dev)
+{
+	struct backlight_properties *props = &dev->props;
+	struct tlc59108_bl *data = dev_get_drvdata(&dev->dev);
+
+	int brightness = props->brightness;
+
+	if (dev->props.state & BL_CORE_FBBLANK) {
+		brightness = 0;
+		/* Set LEDOUT0 Register */
+		i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT0, 0x10);
+	} else {
+		/* Set LEDOUT0 Register */
+		i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT0, 0x30);
+	}
+
+	tlc59108_bl_set_backlight(data, brightness);
+
+	return 0;
+}
+
+static const struct backlight_ops bl_ops = {
+	.get_brightness		= tlc59108_bl_get_brightness,
+	.update_status		= tlc59108_bl_update_status,
+};
+
+static int __devinit tlc59108_probe(struct i2c_client *c, const struct i2c_device_id *id)
+{
+	struct backlight_properties props;
+	struct tlc59108_bl *data = kzalloc(sizeof(struct tlc59108_bl),
+					   GFP_KERNEL);
+	int ret = 0;
+
+	if (!data)
+		return -ENOMEM;
+
+	i2c_set_clientdata(c, data);
+	data->client = c;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = TLC59108_MAX_BRIGHTNESS;
+	props.type = BACKLIGHT_RAW;
+	data->bl = backlight_device_register("tlc59108-bl", &c->dev, data,
+					     &bl_ops, &props);
+	if (IS_ERR(data->bl)) {
+		ret = PTR_ERR(data->bl);
+		goto err_reg;
+	}
+
+	data->bl->props.brightness = TLC59108_MAX_BRIGHTNESS;
+
+	backlight_update_status(data->bl);
+
+	i2c_smbus_write_byte_data(data->client, TLC59108_MODE1, 0x00);
+	i2c_smbus_write_byte_data(data->client, TLC59108_PWM2, 0x80);
+	i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT1, 0x05);
+	i2c_smbus_write_byte_data(data->client, TLC59108_LEDOUT1, 0x15);
+
+	return 0;
+
+err_reg:
+	data->bl = NULL;
+	kfree(data);
+	return ret;
+}
+
+static int tlc59108_remove(struct i2c_client *c)
+{
+	struct tlc59108_bl *data = i2c_get_clientdata(c);
+
+	backlight_device_unregister(data->bl);
+	data->bl = NULL;
+
+	kfree(data);
+
+	return 0;
+}
+
+/* I2C Device ID table */
+static struct i2c_device_id tlc59108_id[] = {
+	{ "tlc59108", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tlc59108_id);
+
+/* I2C driver data */
+static struct i2c_driver tlc59108_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "tlc59108"
+	},
+	.id_table = tlc59108_id,
+	.probe = tlc59108_probe,
+	.remove = tlc59108_remove,
+};
+
+static int __init tlc59108_init(void)
+{
+	return i2c_add_driver(&tlc59108_driver);
+}
+
+static void __exit tlc59108_exit(void)
+{
+	i2c_del_driver(&tlc59108_driver);
+}
+
+module_init(tlc59108_init);
+module_exit(tlc59108_exit);
+
+MODULE_DESCRIPTION("LCD/Backlight control for TLC59108");
+MODULE_AUTHOR("Senthil Natarajan <senthil.n@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c
index 7088163..31a9203 100644
--- a/drivers/video/backlight/tps65217_bl.c
+++ b/drivers/video/backlight/tps65217_bl.c
@@ -24,8 +24,11 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/of_i2c.h>
 
 struct tps65217_bl {
+	struct i2c_client *i2c_client;
 	struct tps65217 *tps;
 	struct device *dev;
 	struct backlight_device *bl;
@@ -98,8 +101,6 @@ static int tps65217_bl_update_status(struct backlight_device *bl)
 			return rc;
 		}
 
-		dev_dbg(tps65217_bl->dev, "brightness set to %d\n", brightness);
-
 		if (!tps65217_bl->is_enabled)
 			rc = tps65217_bl_enable(tps65217_bl);
 	} else {
@@ -187,16 +188,73 @@ static int tps65217_bl_hw_init(struct tps65217_bl *tps65217_bl,
 
 #ifdef CONFIG_OF
 static struct tps65217_bl_pdata *
-tps65217_bl_parse_dt(struct platform_device *pdev)
+tps65217_bl_parse_dt(struct platform_device *pdev, struct tps65217 **tpsp,
+		int *brightnessp)
 {
-	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
-	struct device_node *node = of_node_get(tps->dev->of_node);
+	struct i2c_client *i2c_client;
+	struct tps65217 *tps;
+	struct device_node *node, *rnode, *pnode;
 	struct tps65217_bl_pdata *pdata, *err;
+	u32 tps_handle;
 	u32 val;
 
-	node = of_find_node_by_name(node, "backlight");
-	if (!node)
+	tps = NULL;
+	node = NULL;
+	*brightnessp = 0;
+
+	/* our node (compatible) */
+	pnode = pdev->dev.of_node;
+	if (pnode != NULL &&
+		of_property_read_u32(pnode, "tps", &tps_handle) == 0) {
+		/* we are not instantiated from the mfd */
+		node = of_find_node_by_phandle(tps_handle);
+		if (node == NULL) {
+			dev_err(&pdev->dev, "failed to find the tps node\n");
+			err = ERR_PTR(-EINVAL);
+			goto err;
+		}
+		i2c_client = of_find_i2c_device_by_node(node);
+		if (i2c_client == NULL) {
+			dev_err(&pdev->dev, "failed to find the i2c device "
+					"of tps node\n");
+			err = ERR_PTR(-EINVAL);
+			goto err;
+		}
+		/* yeah this is gross; the whole concept is */
+		tps = i2c_get_clientdata(i2c_client);
+		if (tps == NULL) {
+			dev_err(&pdev->dev, "failed to get tps structure\n");
+			err = ERR_PTR(-EINVAL);
+			goto err;
+		}
+
+		/* read default brightness */
+		val = 0;
+		of_property_read_u32(pnode, "brightness", &val);
+		if (val >= 100)
+			val = 100;
+
+		*brightnessp = val;
+
+		/* no need for this anymore */
+		of_node_put(node);
+
+		dev_info(&pdev->dev, "got tps=%p from handle 0x%x\n", tps, tps_handle);
+	}
+
+	if (tps == NULL)
+		tps = dev_get_drvdata(pdev->dev.parent);
+
+	rnode = of_node_get(tps->dev->of_node);
+
+	node = of_get_child_by_name(rnode, "backlight");
+	of_node_put(rnode);
+	rnode = NULL;
+
+	if (!node) {
+		dev_err(&pdev->dev, "failed to find backlight node\n");
 		return ERR_PTR(-ENODEV);
+	}
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
@@ -247,6 +305,7 @@ tps65217_bl_parse_dt(struct platform_device *pdev)
 
 	of_node_put(node);
 
+	*tpsp = tps;
 	return pdata;
 
 err:
@@ -254,9 +313,16 @@ err:
 
 	return err;
 }
+
+static struct of_device_id tps65217_backlight_of_match[] = {
+	{ .compatible = "tps65217-backlight" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tps65217_backlight_of_match);
 #else
 static struct tps65217_bl_pdata *
-tps65217_bl_parse_dt(struct platform_device *pdev)
+tps65217_bl_parse_dt(struct platform_device *pdev, struct tps65217 **tpsp,
+		int *brightnessp)
 {
 	return NULL;
 }
@@ -265,15 +331,20 @@ tps65217_bl_parse_dt(struct platform_device *pdev)
 static int tps65217_bl_probe(struct platform_device *pdev)
 {
 	int rc;
-	struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+	struct tps65217 *tps;
 	struct tps65217_bl *tps65217_bl;
 	struct tps65217_bl_pdata *pdata;
 	struct backlight_properties bl_props;
+	int brightness = 0;
 
-	if (tps->dev->of_node) {
-		pdata = tps65217_bl_parse_dt(pdev);
-		if (IS_ERR(pdata))
+	tps = NULL;
+
+	if (pdev->dev.of_node) {
+		pdata = tps65217_bl_parse_dt(pdev, &tps, &brightness);
+		if (IS_ERR(pdata)) {
+			dev_err(&pdev->dev, "DT parse failed.\n");
 			return PTR_ERR(pdata);
+		}
 	} else {
 		if (!pdev->dev.platform_data) {
 			dev_err(&pdev->dev, "no platform data provided\n");
@@ -281,6 +352,14 @@ static int tps65217_bl_probe(struct platform_device *pdev)
 		}
 
 		pdata = pdev->dev.platform_data;
+
+		/* get the parent device */
+		tps = dev_get_drvdata(pdev->dev.parent);
+	}
+
+	if (tps == NULL) {
+		dev_err(&pdev->dev, "failed to find tps\n");
+		return -EINVAL;
 	}
 
 	tps65217_bl = devm_kzalloc(&pdev->dev, sizeof(*tps65217_bl),
@@ -311,9 +390,14 @@ static int tps65217_bl_probe(struct platform_device *pdev)
 		return PTR_ERR(tps65217_bl->bl);
 	}
 
-	tps65217_bl->bl->props.brightness = 0;
+	tps65217_bl->bl->props.brightness = brightness;
 	platform_set_drvdata(pdev, tps65217_bl);
 
+	/* update with initial settings */
+	tps65217_bl_update_status(tps65217_bl->bl);
+
+	dev_info(&pdev->dev, "OK.\n");
+
 	return 0;
 }
 
@@ -332,6 +416,7 @@ static struct platform_driver tps65217_bl_driver = {
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "tps65217-bl",
+		.of_match_table	= of_match_ptr(tps65217_backlight_of_match),
 	},
 };
 
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 0810939..6723683 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -36,6 +36,8 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/lcm.h>
+#include <linux/clk-provider.h>
+#include <video/of_display_timing.h>
 #include <video/da8xx-fb.h>
 #include <asm/div64.h>
 
@@ -131,10 +133,10 @@
 
 #define WSI_TIMEOUT	50
 #define PALETTE_SIZE	256
-#define LEFT_MARGIN	64
-#define RIGHT_MARGIN	64
-#define UPPER_MARGIN	32
-#define LOWER_MARGIN	32
+
+#define	LCD_CLK_SHIFT	8
+#define	LCD_CLK_WIDTH	8
+#define	LCD_CLK_MIN_DIV	2
 
 static void __iomem *da8xx_fb_reg_base;
 static struct resource *lcdc_regs;
@@ -145,15 +147,16 @@ static int frame_done_flag;
 
 static inline unsigned int lcdc_read(unsigned int addr)
 {
-	return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr));
+	return (unsigned int)readl(da8xx_fb_reg_base + (addr));
 }
 
 static inline void lcdc_write(unsigned int val, unsigned int addr)
 {
-	__raw_writel(val, da8xx_fb_reg_base + (addr));
+	writel(val, da8xx_fb_reg_base + (addr));
 }
 
 struct da8xx_fb_par {
+	struct device		*dev;
 	resource_size_t p_palette_base;
 	unsigned char *v_palette_base;
 	dma_addr_t		vram_phys;
@@ -164,7 +167,6 @@ struct da8xx_fb_par {
 	struct clk *lcdc_clk;
 	int irq;
 	unsigned int palette_sz;
-	unsigned int pxl_clk;
 	int blank;
 	wait_queue_head_t	vsync_wait;
 	int			vsync_flag;
@@ -178,29 +180,18 @@ struct da8xx_fb_par {
 	unsigned int		which_dma_channel_done;
 #ifdef CONFIG_CPU_FREQ
 	struct notifier_block	freq_transition;
-	unsigned int		lcd_fck_rate;
 #endif
+	unsigned int		lcd_fck_rate;
 	void (*panel_power_ctrl)(int);
 	u32 pseudo_palette[16];
+	struct fb_videomode	mode;
+	struct lcd_ctrl_config	cfg;
+#ifdef CONFIG_COMMON_CLK
+	struct clk		*child_clk;
+#endif
 };
 
-/* Variable Screen Information */
-static struct fb_var_screeninfo da8xx_fb_var = {
-	.xoffset = 0,
-	.yoffset = 0,
-	.transp = {0, 0, 0},
-	.nonstd = 0,
-	.activate = 0,
-	.height = -1,
-	.width = -1,
-	.accel_flags = 0,
-	.left_margin = LEFT_MARGIN,
-	.right_margin = RIGHT_MARGIN,
-	.upper_margin = UPPER_MARGIN,
-	.lower_margin = LOWER_MARGIN,
-	.sync = 0,
-	.vmode = FB_VMODE_NONINTERLACED
-};
+static struct fb_var_screeninfo da8xx_fb_var;
 
 static struct fb_fix_screeninfo da8xx_fb_fix = {
 	.id = "DA8xx FB Drv",
@@ -219,7 +210,7 @@ static struct fb_videomode known_lcd_panels[] = {
 		.name           = "Sharp_LCD035Q3DG01",
 		.xres           = 320,
 		.yres           = 240,
-		.pixclock       = 4608000,
+		.pixclock       = 217014,
 		.left_margin    = 6,
 		.right_margin   = 8,
 		.upper_margin   = 2,
@@ -234,7 +225,7 @@ static struct fb_videomode known_lcd_panels[] = {
 		.name           = "Sharp_LK043T1DG01",
 		.xres           = 480,
 		.yres           = 272,
-		.pixclock       = 7833600,
+		.pixclock       = 127655,
 		.left_margin    = 2,
 		.right_margin   = 2,
 		.upper_margin   = 2,
@@ -249,7 +240,7 @@ static struct fb_videomode known_lcd_panels[] = {
 		.name           = "SP10Q010",
 		.xres           = 320,
 		.yres           = 240,
-		.pixclock       = 7833600,
+		.pixclock       = 127655,
 		.left_margin    = 10,
 		.right_margin   = 10,
 		.upper_margin   = 10,
@@ -261,6 +252,11 @@ static struct fb_videomode known_lcd_panels[] = {
 	},
 };
 
+static inline bool da8xx_fb_is_raster_enabled(void)
+{
+	return !!(lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE);
+}
+
 /* Enable the Raster Engine of the LCD Controller */
 static inline void lcd_enable_raster(void)
 {
@@ -331,7 +327,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
 			reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
 				LCD_V2_END_OF_FRAME0_INT_ENA |
 				LCD_V2_END_OF_FRAME1_INT_ENA |
-				LCD_FRAME_DONE;
+				LCD_FRAME_DONE | LCD_SYNC_LOST;
 			lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
 		}
 		reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
@@ -563,10 +559,10 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
 	case 4:
 	case 16:
 		break;
-	case 24:
-		reg |= LCD_V2_TFT_24BPP_MODE;
 	case 32:
 		reg |= LCD_V2_TFT_24BPP_UNPACK;
+	case 24:
+		reg |= LCD_V2_TFT_24BPP_MODE;
 		break;
 
 	case 8:
@@ -681,11 +677,8 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
 }
 #undef CNVT_TOHW
 
-static void lcd_reset(struct da8xx_fb_par *par)
+static void da8xx_fb_lcd_reset(void)
 {
-	/* Disable the Raster if previously Enabled */
-	lcd_disable_raster(false);
-
 	/* DMA has to be disabled */
 	lcdc_write(0, LCD_DMA_CTRL_REG);
 	lcdc_write(0, LCD_RASTER_CTRL_REG);
@@ -698,22 +691,78 @@ static void lcd_reset(struct da8xx_fb_par *par)
 	}
 }
 
-static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
+#ifndef	CONFIG_COMMON_CLK
+static inline unsigned da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par,
+						 unsigned pixclock)
+{
+	return par->lcd_fck_rate / (PICOS2KHZ(pixclock) * 1000);
+}
+#endif
+
+#ifdef	CONFIG_COMMON_CLK
+static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
+					  unsigned pixclock)
+{
+	unsigned long rate;
+
+	rate = PICOS2KHZ(pixclock) * 1000;
+	rate = clk_round_rate(par->child_clk, rate);
+	rate = KHZ2PICOS(rate / 1000);
+
+	return rate;
+}
+#else
+static inline unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par,
+					  unsigned pixclock)
 {
-	unsigned int lcd_clk, div;
+	unsigned div;
 
-	lcd_clk = clk_get_rate(par->lcdc_clk);
-	div = lcd_clk / par->pxl_clk;
+	div = da8xx_fb_calc_clk_divider(par, pixclock);
+	return KHZ2PICOS(par->lcd_fck_rate / (1000 * div));
+}
 
+static inline void da8xx_fb_config_clk_divider(unsigned div)
+{
 	/* Configure the LCD clock divisor. */
 	lcdc_write(LCD_CLK_DIVISOR(div) |
 			(LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
+}
+#endif
 
+static inline void da8xx_fb_clkc_enable(void)
+{
 	if (lcd_revision == LCD_VERSION_2)
 		lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN |
 				LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG);
+}
+
+#ifdef	CONFIG_COMMON_CLK
+static inline int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
+						    struct fb_videomode *mode)
+{
+	int ret;
+
+	ret = clk_set_rate(par->child_clk, PICOS2KHZ(mode->pixclock) * 1000);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(par->dev, "unable to setup pixel clock of %u ps",
+			mode->pixclock);
+		return ret;
+	}
+	da8xx_fb_clkc_enable();
+	return 0;
+}
+#else
+static inline int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par,
+						    struct fb_videomode *mode)
+{
+	unsigned div = da8xx_fb_calc_clk_divider(par, mode->pixclock);
 
+	da8xx_fb_config_clk_divider(div);
+	da8xx_fb_clkc_enable();
+
+	return 0;
 }
+#endif
 
 static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
 		struct fb_videomode *panel)
@@ -721,10 +770,9 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
 	u32 bpp;
 	int ret = 0;
 
-	lcd_reset(par);
-
-	/* Calculate the divider */
-	lcd_calc_clk_divider(par);
+	ret = da8xx_fb_calc_config_clk_divider(par, panel);
+	if (IS_ERR_VALUE(ret))
+		return ret;
 
 	if (panel->sync & FB_SYNC_CLK_INVERT)
 		lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
@@ -888,6 +936,9 @@ static int fb_check_var(struct fb_var_screeninfo *var,
 			struct fb_info *info)
 {
 	int err = 0;
+	struct da8xx_fb_par *par = info->par;
+	int bpp = var->bits_per_pixel >> 3;
+	unsigned long line_size = var->xres_virtual * bpp;
 
 	if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
 		return -EINVAL;
@@ -955,6 +1006,23 @@ static int fb_check_var(struct fb_var_screeninfo *var,
 	var->green.msb_right = 0;
 	var->blue.msb_right = 0;
 	var->transp.msb_right = 0;
+
+	if (line_size * var->yres_virtual > par->vram_size)
+		var->yres_virtual = par->vram_size / line_size;
+
+	if (var->yres > var->yres_virtual)
+		var->yres = var->yres_virtual;
+
+	if (var->xres > var->xres_virtual)
+		var->xres = var->xres_virtual;
+
+	if (var->xres + var->xoffset > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yres + var->yoffset > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	var->pixclock = da8xx_fb_round_clk(par, var->pixclock);
+
 	return err;
 }
 
@@ -969,7 +1037,7 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
 		if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) {
 			par->lcd_fck_rate = clk_get_rate(par->lcdc_clk);
 			lcd_disable_raster(true);
-			lcd_calc_clk_divider(par);
+			da8xx_fb_calc_config_clk_divider(par, &par->mode);
 			if (par->blank == FB_BLANK_UNBLANK)
 				lcd_enable_raster();
 		}
@@ -1018,12 +1086,9 @@ static int fb_remove(struct platform_device *dev)
 				  par->p_palette_base);
 		dma_free_coherent(NULL, par->vram_size, par->vram_virt,
 				  par->vram_phys);
-		free_irq(par->irq, par);
 		pm_runtime_put_sync(&dev->dev);
 		pm_runtime_disable(&dev->dev);
 		framebuffer_release(info);
-		iounmap(da8xx_fb_reg_base);
-		release_mem_region(lcdc_regs->start, resource_size(lcdc_regs));
 
 	}
 	return 0;
@@ -1183,9 +1248,52 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var,
 	return ret;
 }
 
+static int da8xxfb_set_par(struct fb_info *info)
+{
+	struct da8xx_fb_par *par = info->par;
+	int ret;
+	bool raster = da8xx_fb_is_raster_enabled();
+
+	if (raster)
+		lcd_disable_raster(true);
+	else
+		lcd_disable_raster(false);
+
+	fb_var_to_videomode(&par->mode, &info->var);
+
+	par->cfg.bpp = info->var.bits_per_pixel;
+
+	info->fix.visual = (par->cfg.bpp <= 8) ?
+				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = (par->mode.xres * par->cfg.bpp) / 8;
+
+	ret = lcd_init(par, &par->cfg, &par->mode);
+	if (ret < 0) {
+		dev_err(par->dev, "lcd init failed\n");
+		return ret;
+	}
+
+	par->dma_start = info->fix.smem_start +
+			 info->var.yoffset * info->fix.line_length +
+			 info->var.xoffset * info->var.bits_per_pixel / 8;
+	par->dma_end   = par->dma_start +
+			 info->var.yres * info->fix.line_length - 1;
+
+	lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
+	lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
+	lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
+	lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
+
+	if (raster)
+		lcd_enable_raster();
+
+	return 0;
+}
+
 static struct fb_ops da8xx_fb_ops = {
 	.owner = THIS_MODULE,
 	.fb_check_var = fb_check_var,
+	.fb_set_par = da8xxfb_set_par,
 	.fb_setcolreg = fb_setcolreg,
 	.fb_pan_display = da8xx_pan_display,
 	.fb_ioctl = fb_ioctl,
@@ -1195,20 +1303,70 @@ static struct fb_ops da8xx_fb_ops = {
 	.fb_blank = cfb_blank,
 };
 
-/* Calculate and return pixel clock period in pico seconds */
-static unsigned int da8xxfb_pixel_clk_period(struct da8xx_fb_par *par)
+static struct lcd_ctrl_config *da8xx_fb_create_cfg(struct platform_device *dev)
+{
+	struct lcd_ctrl_config *cfg;
+
+	cfg = devm_kzalloc(&dev->dev, sizeof(struct fb_videomode), GFP_KERNEL);
+	if (!cfg) {
+		dev_err(&dev->dev, "memory allocation failed\n");
+		return NULL;
+	}
+
+	/* default values */
+
+	if (lcd_revision == LCD_VERSION_1)
+		cfg->bpp = 16;
+	else
+		cfg->bpp = 32;
+
+	/*
+	 * For panels so far used with this LCDC, below statement is sufficient.
+	 * For new panels, if required, struct lcd_ctrl_cfg fields to be updated
+	 * with additional/modified values. Those values would have to be then
+	 * obtained from dt(requiring new dt bindings).
+	 */
+
+	cfg->panel_shade = COLOR_ACTIVE;
+
+	return cfg;
+}
+
+static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev)
 {
-	unsigned int lcd_clk, div;
-	unsigned int configured_pix_clk;
-	unsigned long long pix_clk_period_picosec = 1000000000000ULL;
+	struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data;
+	struct fb_videomode *lcdc_info;
+	struct device_node *np = dev->dev.of_node;
+	int i;
+
+	if (np) {
+		lcdc_info = devm_kzalloc(&dev->dev,
+					 sizeof(struct fb_videomode),
+					 GFP_KERNEL);
+		if (!lcdc_info) {
+			dev_err(&dev->dev, "memory allocation failed\n");
+			return NULL;
+		}
+		if (of_get_fb_videomode(np, lcdc_info, OF_USE_NATIVE_MODE)) {
+			dev_err(&dev->dev, "timings not available in DT\n");
+			return NULL;
+		}
+		return lcdc_info;
+	}
 
-	lcd_clk = clk_get_rate(par->lcdc_clk);
-	div = lcd_clk / par->pxl_clk;
-	configured_pix_clk = (lcd_clk / div);
+	for (i = 0, lcdc_info = known_lcd_panels;
+		i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) {
+		if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
+			break;
+	}
 
-	do_div(pix_clk_period_picosec, configured_pix_clk);
+	if (i == ARRAY_SIZE(known_lcd_panels)) {
+		dev_err(&dev->dev, "no panel found\n");
+		return NULL;
+	}
+	dev_info(&dev->dev, "found %s panel\n", lcdc_info->name);
 
-	return pix_clk_period_picosec;
+	return lcdc_info;
 }
 
 static int fb_probe(struct platform_device *device)
@@ -1220,39 +1378,29 @@ static int fb_probe(struct platform_device *device)
 	struct fb_info *da8xx_fb_info;
 	struct clk *fb_clk = NULL;
 	struct da8xx_fb_par *par;
-	resource_size_t len;
-	int ret, i;
+	int ret;
 	unsigned long ulcm;
 
-	if (fb_pdata == NULL) {
+	if (fb_pdata == NULL && !device->dev.of_node) {
 		dev_err(&device->dev, "Can not get platform data\n");
 		return -ENOENT;
 	}
 
-	lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
-	if (!lcdc_regs) {
-		dev_err(&device->dev,
-			"Can not get memory resource for LCD controller\n");
-		return -ENOENT;
-	}
-
-	len = resource_size(lcdc_regs);
+	lcdc_info = da8xx_fb_get_videomode(device);
+	if (lcdc_info == NULL)
+		return -ENODEV;
 
-	lcdc_regs = request_mem_region(lcdc_regs->start, len, lcdc_regs->name);
-	if (!lcdc_regs)
-		return -EBUSY;
-
-	da8xx_fb_reg_base = ioremap(lcdc_regs->start, len);
+	lcdc_regs = platform_get_resource(device, IORESOURCE_MEM, 0);
+	da8xx_fb_reg_base = devm_request_and_ioremap(&device->dev, lcdc_regs);
 	if (!da8xx_fb_reg_base) {
-		ret = -EBUSY;
-		goto err_request_mem;
+		dev_err(&device->dev, "memory resource setup failed\n");
+		return -EADDRNOTAVAIL;
 	}
 
-	fb_clk = clk_get(&device->dev, "fck");
+	fb_clk = devm_clk_get(&device->dev, "fck");
 	if (IS_ERR(fb_clk)) {
 		dev_err(&device->dev, "Can not get device clock\n");
-		ret = -ENODEV;
-		goto err_ioremap;
+		return -ENODEV;
 	}
 
 	pm_runtime_enable(&device->dev);
@@ -1275,22 +1423,15 @@ static int fb_probe(struct platform_device *device)
 		break;
 	}
 
-	for (i = 0, lcdc_info = known_lcd_panels;
-		i < ARRAY_SIZE(known_lcd_panels);
-		i++, lcdc_info++) {
-		if (strcmp(fb_pdata->type, lcdc_info->name) == 0)
-			break;
-	}
+	if (device->dev.of_node)
+		lcd_cfg = da8xx_fb_create_cfg(device);
+	else
+		lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
 
-	if (i == ARRAY_SIZE(known_lcd_panels)) {
-		dev_err(&device->dev, "GLCD: No valid panel found\n");
-		ret = -ENODEV;
+	if (!lcd_cfg) {
+		ret = -EINVAL;
 		goto err_pm_runtime_disable;
-	} else
-		dev_info(&device->dev, "GLCD: Found %s panel\n",
-					fb_pdata->type);
-
-	lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data;
+	}
 
 	da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par),
 					&device->dev);
@@ -1301,21 +1442,37 @@ static int fb_probe(struct platform_device *device)
 	}
 
 	par = da8xx_fb_info->par;
+	par->dev = &device->dev;
 	par->lcdc_clk = fb_clk;
-#ifdef CONFIG_CPU_FREQ
 	par->lcd_fck_rate = clk_get_rate(fb_clk);
-#endif
-	par->pxl_clk = lcdc_info->pixclock;
-	if (fb_pdata->panel_power_ctrl) {
+	if (fb_pdata && fb_pdata->panel_power_ctrl) {
 		par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
 		par->panel_power_ctrl(1);
 	}
 
-	if (lcd_init(par, lcd_cfg, lcdc_info) < 0) {
-		dev_err(&device->dev, "lcd_init failed\n");
-		ret = -EFAULT;
+	fb_videomode_to_var(&da8xx_fb_var, lcdc_info);
+	par->cfg = *lcd_cfg;
+
+	da8xx_fb_lcd_reset();
+
+#ifdef	CONFIG_COMMON_CLK
+	/* set sane divisor value to begin along with the mode */
+	lcdc_write(LCD_RASTER_MODE | LCD_CLK_DIVISOR(LCD_CLK_MIN_DIV),
+		   LCD_CTRL_REG);
+
+	par->child_clk = clk_register_min_divider(NULL, "da8xx_fb_clk",
+					      __clk_get_name(fb_clk),
+					      CLK_SET_RATE_PARENT,
+					      da8xx_fb_reg_base + LCD_CTRL_REG,
+					      LCD_CLK_SHIFT, LCD_CLK_WIDTH,
+					      LCD_CLK_MIN_DIV,
+					      CLK_DIVIDER_ONE_BASED, NULL);
+	if (IS_ERR(par->child_clk)) {
+		dev_err(&device->dev, "error registering clk\n");
+		ret = -ENODEV;
 		goto err_release_fb;
 	}
+#endif
 
 	/* allocate frame buffer */
 	par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp;
@@ -1363,27 +1520,10 @@ static int fb_probe(struct platform_device *device)
 		goto err_release_pl_mem;
 	}
 
-	/* Initialize par */
-	da8xx_fb_info->var.bits_per_pixel = lcd_cfg->bpp;
-
-	da8xx_fb_var.xres = lcdc_info->xres;
-	da8xx_fb_var.xres_virtual = lcdc_info->xres;
-
-	da8xx_fb_var.yres         = lcdc_info->yres;
-	da8xx_fb_var.yres_virtual = lcdc_info->yres * LCD_NUM_BUFFERS;
-
 	da8xx_fb_var.grayscale =
 	    lcd_cfg->panel_shade == MONOCHROME ? 1 : 0;
 	da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp;
 
-	da8xx_fb_var.hsync_len = lcdc_info->hsync_len;
-	da8xx_fb_var.vsync_len = lcdc_info->vsync_len;
-	da8xx_fb_var.right_margin = lcdc_info->right_margin;
-	da8xx_fb_var.left_margin  = lcdc_info->left_margin;
-	da8xx_fb_var.lower_margin = lcdc_info->lower_margin;
-	da8xx_fb_var.upper_margin = lcdc_info->upper_margin;
-	da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
-
 	/* Initialize fbinfo */
 	da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
 	da8xx_fb_info->fix = da8xx_fb_fix;
@@ -1433,7 +1573,7 @@ static int fb_probe(struct platform_device *device)
 		lcdc_irq_handler = lcdc_irq_handler_rev02;
 	}
 
-	ret = request_irq(par->irq, lcdc_irq_handler, 0,
+	ret = devm_request_irq(&device->dev, par->irq, lcdc_irq_handler, 0,
 			DRIVER_NAME, par);
 	if (ret)
 		goto irq_freq;
@@ -1463,12 +1603,6 @@ err_pm_runtime_disable:
 	pm_runtime_put_sync(&device->dev);
 	pm_runtime_disable(&device->dev);
 
-err_ioremap:
-	iounmap(da8xx_fb_reg_base);
-
-err_request_mem:
-	release_mem_region(lcdc_regs->start, len);
-
 	return ret;
 }
 
@@ -1578,6 +1712,12 @@ static int fb_resume(struct platform_device *dev)
 #define fb_resume NULL
 #endif
 
+static const struct of_device_id da8xx_fb_of_match[] = {
+	{.compatible = "ti,da830-lcdc", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, da8xx_fb_of_match);
+
 static struct platform_driver da8xx_fb_driver = {
 	.probe = fb_probe,
 	.remove = fb_remove,
@@ -1586,6 +1726,7 @@ static struct platform_driver da8xx_fb_driver = {
 	.driver = {
 		   .name = DRIVER_NAME,
 		   .owner = THIS_MODULE,
+		   .of_match_table = of_match_ptr(da8xx_fb_of_match),
 		   },
 };
 
diff --git a/drivers/video/display_timing.c b/drivers/video/display_timing.c
new file mode 100644
index 0000000..5e1822c
--- /dev/null
+++ b/drivers/video/display_timing.c
@@ -0,0 +1,24 @@
+/*
+ * generic display timing functions
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * This file is released under the GPLv2
+ */
+
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <video/display_timing.h>
+
+void display_timings_release(struct display_timings *disp)
+{
+	if (disp->timings) {
+		unsigned int i;
+
+		for (i = 0; i < disp->num_timings; i++)
+			kfree(disp->timings[i]);
+		kfree(disp->timings);
+	}
+	kfree(disp);
+}
+EXPORT_SYMBOL_GPL(display_timings_release);
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index cef6557..94ad0f7 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -31,6 +31,8 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <video/edid.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
 #ifdef CONFIG_PPC_OF
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
@@ -1373,6 +1375,98 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
 	kfree(timings);
 	return err;
 }
+
+#if IS_ENABLED(CONFIG_VIDEOMODE)
+int fb_videomode_from_videomode(const struct videomode *vm,
+				struct fb_videomode *fbmode)
+{
+	unsigned int htotal, vtotal;
+
+	fbmode->xres = vm->hactive;
+	fbmode->left_margin = vm->hback_porch;
+	fbmode->right_margin = vm->hfront_porch;
+	fbmode->hsync_len = vm->hsync_len;
+
+	fbmode->yres = vm->vactive;
+	fbmode->upper_margin = vm->vback_porch;
+	fbmode->lower_margin = vm->vfront_porch;
+	fbmode->vsync_len = vm->vsync_len;
+
+	/* prevent division by zero in KHZ2PICOS macro */
+	fbmode->pixclock = vm->pixelclock ?
+			KHZ2PICOS(vm->pixelclock / 1000) : 0;
+
+	fbmode->sync = 0;
+	fbmode->vmode = 0;
+	if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
+		fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
+		fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
+	if (vm->data_flags & DISPLAY_FLAGS_INTERLACED)
+		fbmode->vmode |= FB_VMODE_INTERLACED;
+	if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN)
+		fbmode->vmode |= FB_VMODE_DOUBLE;
+	fbmode->flag = 0;
+
+	htotal = vm->hactive + vm->hfront_porch + vm->hback_porch +
+		 vm->hsync_len;
+	vtotal = vm->vactive + vm->vfront_porch + vm->vback_porch +
+		 vm->vsync_len;
+	/* prevent division by zero */
+	if (htotal && vtotal) {
+		fbmode->refresh = vm->pixelclock / (htotal * vtotal);
+	/* a mode must have htotal and vtotal != 0 or it is invalid */
+	} else {
+		fbmode->refresh = 0;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
+#endif
+
+#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+static inline void dump_fb_videomode(const struct fb_videomode *m)
+{
+	pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n",
+		 m->xres, m->yres, m->refresh, m->pixclock, m->left_margin,
+		 m->right_margin, m->upper_margin, m->lower_margin,
+		 m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
+}
+
+/**
+ * of_get_fb_videomode - get a fb_videomode from devicetree
+ * @np: device_node with the timing specification
+ * @fb: will be set to the return value
+ * @index: index into the list of display timings in devicetree
+ *
+ * DESCRIPTION:
+ * This function is expensive and should only be used, if only one mode is to be
+ * read from DT. To get multiple modes start with of_get_display_timings ond
+ * work with that instead.
+ */
+int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb,
+			int index)
+{
+	struct videomode vm;
+	int ret;
+
+	ret = of_get_videomode(np, &vm, index);
+	if (ret)
+		return ret;
+
+	fb_videomode_from_videomode(&vm, fb);
+
+	pr_debug("%s: got %dx%d display mode from %s\n",
+		of_node_full_name(np), vm.hactive, vm.vactive, np->name);
+	dump_fb_videomode(fb);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_fb_videomode);
+#endif
+
 #else
 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
 {
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c
new file mode 100644
index 0000000..ab23c9b
--- /dev/null
+++ b/drivers/video/hdmi.c
@@ -0,0 +1,308 @@
+/*
+ * 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/bitops.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/hdmi.h>
+#include <linux/string.h>
+
+static void hdmi_infoframe_checksum(void *buffer, size_t size)
+{
+	u8 *ptr = buffer;
+	u8 csum = 0;
+	size_t i;
+
+	/* compute checksum */
+	for (i = 0; i < size; i++)
+		csum += ptr[i];
+
+	ptr[3] = 256 - csum;
+}
+
+/**
+ * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe
+ * @frame: HDMI AVI infoframe
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame)
+{
+	memset(frame, 0, sizeof(*frame));
+
+	frame->type = HDMI_INFOFRAME_TYPE_AVI;
+	frame->version = 2;
+	frame->length = 13;
+
+	return 0;
+}
+EXPORT_SYMBOL(hdmi_avi_infoframe_init);
+
+/**
+ * hdmi_avi_infoframe_pack() - write HDMI AVI infoframe to binary buffer
+ * @frame: HDMI AVI infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Packs the information contained in the @frame structure into a binary
+ * representation that can be written into the corresponding controller
+ * registers. Also computes the checksum as required by section 5.3.5 of
+ * the HDMI 1.4 specification.
+ *
+ * Returns the number of bytes packed into the binary buffer or a negative
+ * error code on failure.
+ */
+ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
+				size_t size)
+{
+	u8 *ptr = buffer;
+	size_t length;
+
+	length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
+
+	if (size < length)
+		return -ENOSPC;
+
+	memset(buffer, 0, length);
+
+	ptr[0] = frame->type;
+	ptr[1] = frame->version;
+	ptr[2] = frame->length;
+	ptr[3] = 0; /* checksum */
+
+	/* start infoframe payload */
+	ptr += HDMI_INFOFRAME_HEADER_SIZE;
+
+	ptr[0] = ((frame->colorspace & 0x3) << 5) | (frame->scan_mode & 0x3);
+
+	if (frame->active_info_valid)
+		ptr[0] |= BIT(4);
+
+	if (frame->horizontal_bar_valid)
+		ptr[0] |= BIT(3);
+
+	if (frame->vertical_bar_valid)
+		ptr[0] |= BIT(2);
+
+	ptr[1] = ((frame->colorimetry & 0x3) << 6) |
+		 ((frame->picture_aspect & 0x3) << 4) |
+		 (frame->active_aspect & 0xf);
+
+	ptr[2] = ((frame->extended_colorimetry & 0x7) << 4) |
+		 ((frame->quantization_range & 0x3) << 2) |
+		 (frame->nups & 0x3);
+
+	if (frame->itc)
+		ptr[2] |= BIT(7);
+
+	ptr[3] = frame->video_code & 0x7f;
+
+	ptr[4] = ((frame->ycc_quantization_range & 0x3) << 6) |
+		 ((frame->content_type & 0x3) << 4) |
+		 (frame->pixel_repeat & 0xf);
+
+	ptr[5] = frame->top_bar & 0xff;
+	ptr[6] = (frame->top_bar >> 8) & 0xff;
+	ptr[7] = frame->bottom_bar & 0xff;
+	ptr[8] = (frame->bottom_bar >> 8) & 0xff;
+	ptr[9] = frame->left_bar & 0xff;
+	ptr[10] = (frame->left_bar >> 8) & 0xff;
+	ptr[11] = frame->right_bar & 0xff;
+	ptr[12] = (frame->right_bar >> 8) & 0xff;
+
+	hdmi_infoframe_checksum(buffer, length);
+
+	return length;
+}
+EXPORT_SYMBOL(hdmi_avi_infoframe_pack);
+
+/**
+ * hdmi_spd_infoframe_init() - initialize an HDMI SPD infoframe
+ * @frame: HDMI SPD infoframe
+ * @vendor: vendor string
+ * @product: product string
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
+			    const char *vendor, const char *product)
+{
+	memset(frame, 0, sizeof(*frame));
+
+	frame->type = HDMI_INFOFRAME_TYPE_SPD;
+	frame->version = 1;
+	frame->length = 25;
+
+	strncpy(frame->vendor, vendor, sizeof(frame->vendor));
+	strncpy(frame->product, product, sizeof(frame->product));
+
+	return 0;
+}
+EXPORT_SYMBOL(hdmi_spd_infoframe_init);
+
+/**
+ * hdmi_spd_infoframe_pack() - write HDMI SPD infoframe to binary buffer
+ * @frame: HDMI SPD infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Packs the information contained in the @frame structure into a binary
+ * representation that can be written into the corresponding controller
+ * registers. Also computes the checksum as required by section 5.3.5 of
+ * the HDMI 1.4 specification.
+ *
+ * Returns the number of bytes packed into the binary buffer or a negative
+ * error code on failure.
+ */
+ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
+				size_t size)
+{
+	u8 *ptr = buffer;
+	size_t length;
+
+	length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
+
+	if (size < length)
+		return -ENOSPC;
+
+	memset(buffer, 0, length);
+
+	ptr[0] = frame->type;
+	ptr[1] = frame->version;
+	ptr[2] = frame->length;
+	ptr[3] = 0; /* checksum */
+
+	/* start infoframe payload */
+	ptr += HDMI_INFOFRAME_HEADER_SIZE;
+
+	memcpy(ptr, frame->vendor, sizeof(frame->vendor));
+	memcpy(ptr + 8, frame->product, sizeof(frame->product));
+
+	ptr[24] = frame->sdi;
+
+	hdmi_infoframe_checksum(buffer, length);
+
+	return length;
+}
+EXPORT_SYMBOL(hdmi_spd_infoframe_pack);
+
+/**
+ * hdmi_audio_infoframe_init() - initialize an HDMI audio infoframe
+ * @frame: HDMI audio infoframe
+ *
+ * Returns 0 on success or a negative error code on failure.
+ */
+int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame)
+{
+	memset(frame, 0, sizeof(*frame));
+
+	frame->type = HDMI_INFOFRAME_TYPE_AUDIO;
+	frame->version = 1;
+	frame->length = 10;
+
+	return 0;
+}
+EXPORT_SYMBOL(hdmi_audio_infoframe_init);
+
+/**
+ * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer
+ * @frame: HDMI audio infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Packs the information contained in the @frame structure into a binary
+ * representation that can be written into the corresponding controller
+ * registers. Also computes the checksum as required by section 5.3.5 of
+ * the HDMI 1.4 specification.
+ *
+ * Returns the number of bytes packed into the binary buffer or a negative
+ * error code on failure.
+ */
+ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
+				  void *buffer, size_t size)
+{
+	unsigned char channels;
+	u8 *ptr = buffer;
+	size_t length;
+
+	length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
+
+	if (size < length)
+		return -ENOSPC;
+
+	memset(buffer, 0, length);
+
+	if (frame->channels >= 2)
+		channels = frame->channels - 1;
+	else
+		channels = 0;
+
+	ptr[0] = frame->type;
+	ptr[1] = frame->version;
+	ptr[2] = frame->length;
+	ptr[3] = 0; /* checksum */
+
+	/* start infoframe payload */
+	ptr += HDMI_INFOFRAME_HEADER_SIZE;
+
+	ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7);
+	ptr[1] = ((frame->sample_frequency & 0x7) << 2) |
+		 (frame->sample_size & 0x3);
+	ptr[2] = frame->coding_type_ext & 0x1f;
+	ptr[3] = frame->channel_allocation;
+	ptr[4] = (frame->level_shift_value & 0xf) << 3;
+
+	if (frame->downmix_inhibit)
+		ptr[4] |= BIT(7);
+
+	hdmi_infoframe_checksum(buffer, length);
+
+	return length;
+}
+EXPORT_SYMBOL(hdmi_audio_infoframe_pack);
+
+/**
+ * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary
+ *                                buffer
+ * @frame: HDMI vendor infoframe
+ * @buffer: destination buffer
+ * @size: size of buffer
+ *
+ * Packs the information contained in the @frame structure into a binary
+ * representation that can be written into the corresponding controller
+ * registers. Also computes the checksum as required by section 5.3.5 of
+ * the HDMI 1.4 specification.
+ *
+ * Returns the number of bytes packed into the binary buffer or a negative
+ * error code on failure.
+ */
+ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
+				   void *buffer, size_t size)
+{
+	u8 *ptr = buffer;
+	size_t length;
+
+	length = HDMI_INFOFRAME_HEADER_SIZE + frame->length;
+
+	if (size < length)
+		return -ENOSPC;
+
+	memset(buffer, 0, length);
+
+	ptr[0] = frame->type;
+	ptr[1] = frame->version;
+	ptr[2] = frame->length;
+	ptr[3] = 0; /* checksum */
+
+	memcpy(&ptr[HDMI_INFOFRAME_HEADER_SIZE], frame->data, frame->length);
+
+	hdmi_infoframe_checksum(buffer, length);
+
+	return length;
+}
+EXPORT_SYMBOL(hdmi_vendor_infoframe_pack);
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index a9a907c..69ad1ec 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -103,6 +103,10 @@ static const struct fb_videomode modedb[] = {
 	{ NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0,
 		FB_VMODE_NONINTERLACED },
 
+	/* 1280x720 @ 60 Hz, 45 kHz hsync, CEA 681-E Format 4 */
+	{ "hd720", 60, 1280, 720, 13468, 220, 110, 20, 5, 40, 5, 0,
+		FB_VMODE_NONINTERLACED },
+
 	/* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
 	{ NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12,	0,
 		FB_VMODE_INTERLACED },
@@ -289,6 +293,10 @@ static const struct fb_videomode modedb[] = {
 	/* 864x480 @ 60 Hz, 35.15 kHz hsync */
 	{ NULL, 60, 864, 480, 27777, 1, 1, 1, 1, 0, 0,
 		0, FB_VMODE_NONINTERLACED },
+
+	/* 800x480 @ 60 Hz, Toshiba LTA070B220F 7 inch LCD */
+	{  NULL, 60, 800, 480, 32787, 48, 80, 33, 31, 32, 2,
+		FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED },
 };
 
 #ifdef CONFIG_FB_MODE_HELPERS
diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c
new file mode 100644
index 0000000..c0ea594
--- /dev/null
+++ b/drivers/video/of_display_timing.c
@@ -0,0 +1,239 @@
+/*
+ * OF helpers for parsing display timings
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * based on of_videomode.c by Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ */
+#include <linux/export.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <video/display_timing.h>
+#include <video/of_display_timing.h>
+
+/**
+ * parse_timing_property - parse timing_entry from device_node
+ * @np: device_node with the property
+ * @name: name of the property
+ * @result: will be set to the return value
+ *
+ * DESCRIPTION:
+ * Every display_timing can be specified with either just the typical value or
+ * a range consisting of min/typ/max. This function helps handling this
+ **/
+static int parse_timing_property(struct device_node *np, const char *name,
+			  struct timing_entry *result)
+{
+	struct property *prop;
+	int length, cells, ret;
+
+	prop = of_find_property(np, name, &length);
+	if (!prop) {
+		pr_err("%s: could not find property %s\n",
+			of_node_full_name(np), name);
+		return -EINVAL;
+	}
+
+	cells = length / sizeof(u32);
+	if (cells == 1) {
+		ret = of_property_read_u32(np, name, &result->typ);
+		result->min = result->typ;
+		result->max = result->typ;
+	} else if (cells == 3) {
+		ret = of_property_read_u32_array(np, name, &result->min, cells);
+	} else {
+		pr_err("%s: illegal timing specification in %s\n",
+			of_node_full_name(np), name);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
+ * of_get_display_timing - parse display_timing entry from device_node
+ * @np: device_node with the properties
+ **/
+static struct display_timing *of_get_display_timing(struct device_node *np)
+{
+	struct display_timing *dt;
+	u32 val = 0;
+	int ret = 0;
+
+	dt = kzalloc(sizeof(*dt), GFP_KERNEL);
+	if (!dt) {
+		pr_err("%s: could not allocate display_timing struct\n",
+			of_node_full_name(np));
+		return NULL;
+	}
+
+	ret |= parse_timing_property(np, "hback-porch", &dt->hback_porch);
+	ret |= parse_timing_property(np, "hfront-porch", &dt->hfront_porch);
+	ret |= parse_timing_property(np, "hactive", &dt->hactive);
+	ret |= parse_timing_property(np, "hsync-len", &dt->hsync_len);
+	ret |= parse_timing_property(np, "vback-porch", &dt->vback_porch);
+	ret |= parse_timing_property(np, "vfront-porch", &dt->vfront_porch);
+	ret |= parse_timing_property(np, "vactive", &dt->vactive);
+	ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len);
+	ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
+
+	dt->dmt_flags = 0;
+	dt->data_flags = 0;
+	if (!of_property_read_u32(np, "vsync-active", &val))
+		dt->dmt_flags |= val ? VESA_DMT_VSYNC_HIGH :
+				VESA_DMT_VSYNC_LOW;
+	if (!of_property_read_u32(np, "hsync-active", &val))
+		dt->dmt_flags |= val ? VESA_DMT_HSYNC_HIGH :
+				VESA_DMT_HSYNC_LOW;
+	if (!of_property_read_u32(np, "de-active", &val))
+		dt->data_flags |= val ? DISPLAY_FLAGS_DE_HIGH :
+				DISPLAY_FLAGS_DE_LOW;
+	if (!of_property_read_u32(np, "pixelclk-active", &val))
+		dt->data_flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
+				DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+
+	if (of_property_read_bool(np, "interlaced"))
+		dt->data_flags |= DISPLAY_FLAGS_INTERLACED;
+	if (of_property_read_bool(np, "doublescan"))
+		dt->data_flags |= DISPLAY_FLAGS_DOUBLESCAN;
+
+	if (ret) {
+		pr_err("%s: error reading timing properties\n",
+			of_node_full_name(np));
+		kfree(dt);
+		return NULL;
+	}
+
+	return dt;
+}
+
+/**
+ * of_get_display_timings - parse all display_timing entries from a device_node
+ * @np: device_node with the subnodes
+ **/
+struct display_timings *of_get_display_timings(struct device_node *np)
+{
+	struct device_node *timings_np;
+	struct device_node *entry;
+	struct device_node *native_mode;
+	struct display_timings *disp;
+
+	if (!np) {
+		pr_err("%s: no devicenode given\n", of_node_full_name(np));
+		return NULL;
+	}
+
+	timings_np = of_get_child_by_name(np, "display-timings");
+	if (!timings_np) {
+		pr_err("%s: could not find display-timings node\n",
+			of_node_full_name(np));
+		return NULL;
+	}
+
+	disp = kzalloc(sizeof(*disp), GFP_KERNEL);
+	if (!disp) {
+		pr_err("%s: could not allocate struct disp'\n",
+			of_node_full_name(np));
+		goto dispfail;
+	}
+
+	entry = of_parse_phandle(timings_np, "native-mode", 0);
+	/* assume first child as native mode if none provided */
+	if (!entry)
+		entry = of_get_next_child(np, NULL);
+	/* if there is no child, it is useless to go on */
+	if (!entry) {
+		pr_err("%s: no timing specifications given\n",
+			of_node_full_name(np));
+		goto entryfail;
+	}
+
+	pr_debug("%s: using %s as default timing\n",
+		of_node_full_name(np), entry->name);
+
+	native_mode = entry;
+
+	disp->num_timings = of_get_child_count(timings_np);
+	if (disp->num_timings == 0) {
+		/* should never happen, as entry was already found above */
+		pr_err("%s: no timings specified\n", of_node_full_name(np));
+		goto entryfail;
+	}
+
+	disp->timings = kzalloc(sizeof(struct display_timing *) *
+				disp->num_timings, GFP_KERNEL);
+	if (!disp->timings) {
+		pr_err("%s: could not allocate timings array\n",
+			of_node_full_name(np));
+		goto entryfail;
+	}
+
+	disp->num_timings = 0;
+	disp->native_mode = 0;
+
+	for_each_child_of_node(timings_np, entry) {
+		struct display_timing *dt;
+
+		dt = of_get_display_timing(entry);
+		if (!dt) {
+			/*
+			 * to not encourage wrong devicetrees, fail in case of
+			 * an error
+			 */
+			pr_err("%s: error in timing %d\n",
+				of_node_full_name(np), disp->num_timings + 1);
+			goto timingfail;
+		}
+
+		if (native_mode == entry)
+			disp->native_mode = disp->num_timings;
+
+		disp->timings[disp->num_timings] = dt;
+		disp->num_timings++;
+	}
+	of_node_put(timings_np);
+	/*
+	 * native_mode points to the device_node returned by of_parse_phandle
+	 * therefore call of_node_put on it
+	 */
+	of_node_put(native_mode);
+
+	pr_debug("%s: got %d timings. Using timing #%d as default\n",
+		of_node_full_name(np), disp->num_timings,
+		disp->native_mode + 1);
+
+	return disp;
+
+timingfail:
+	if (native_mode)
+		of_node_put(native_mode);
+	display_timings_release(disp);
+entryfail:
+	kfree(disp);
+dispfail:
+	of_node_put(timings_np);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(of_get_display_timings);
+
+/**
+ * of_display_timings_exist - check if a display-timings node is provided
+ * @np: device_node with the timing
+ **/
+int of_display_timings_exist(struct device_node *np)
+{
+	struct device_node *timings_np;
+
+	if (!np)
+		return -EINVAL;
+
+	timings_np = of_parse_phandle(np, "display-timings", 0);
+	if (!timings_np)
+		return -EINVAL;
+
+	of_node_put(timings_np);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(of_display_timings_exist);
diff --git a/drivers/video/of_videomode.c b/drivers/video/of_videomode.c
new file mode 100644
index 0000000..5b8066c
--- /dev/null
+++ b/drivers/video/of_videomode.c
@@ -0,0 +1,54 @@
+/*
+ * generic videomode helper
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * This file is released under the GPLv2
+ */
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/of.h>
+#include <video/display_timing.h>
+#include <video/of_display_timing.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+/**
+ * of_get_videomode - get the videomode #<index> from devicetree
+ * @np - devicenode with the display_timings
+ * @vm - set to return value
+ * @index - index into list of display_timings
+ *	    (Set this to OF_USE_NATIVE_MODE to use whatever mode is
+ *	     specified as native mode in the DT.)
+ *
+ * DESCRIPTION:
+ * Get a list of all display timings and put the one
+ * specified by index into *vm. This function should only be used, if
+ * only one videomode is to be retrieved. A driver that needs to work
+ * with multiple/all videomodes should work with
+ * of_get_display_timings instead.
+ **/
+int of_get_videomode(struct device_node *np, struct videomode *vm,
+		     int index)
+{
+	struct display_timings *disp;
+	int ret;
+
+	disp = of_get_display_timings(np);
+	if (!disp) {
+		pr_err("%s: no timings specified\n", of_node_full_name(np));
+		return -EINVAL;
+	}
+
+	if (index == OF_USE_NATIVE_MODE)
+		index = disp->native_mode;
+
+	ret = videomode_from_timing(disp, vm, index);
+	if (ret)
+		return ret;
+
+	display_timings_release(disp);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_videomode);
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 54ca8ae..f176003 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -538,6 +538,33 @@ static struct panel_config generic_dpi_panels[] = {
 		},
 		.name			= "primeview_pd104slf",
 	},
+
+	/* ThreeFiveCorp S9700RTWV35TR-01B */
+	{
+		{
+			.x_res		= 800,
+			.y_res		= 480,
+
+			.pixel_clock	= 30000,
+
+			.hsw		= 49,
+			.hfp		= 41,
+			.hbp		= 40,
+
+			.vsw		= 4,
+			.vfp		= 14,
+			.vbp		= 29,
+
+			.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+			.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+			.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
+			.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+			.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
+		},
+		.power_on_delay		= 50,
+		.power_off_delay	= 100,
+		.name			= "tfc_s9700rtwv35tr-01b",
+	},
 };
 
 struct panel_drv_data {
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 006caf3..0e5b3b1 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -86,6 +86,11 @@
 #define VENC_OUTPUT_TEST			0xC8
 #define VENC_DAC_B__DAC_C			0xC8
 
+static char *tv_connection;
+
+module_param_named(tvcable, tv_connection, charp, 0);
+MODULE_PARM_DESC(tvcable, "TV connection type (svideo, composite)");
+
 struct venc_config {
 	u32 f_control;
 	u32 vidout_ctrl;
@@ -465,6 +470,23 @@ static int venc_power_on(struct omap_dss_device *dssdev)
 	if (r)
 		goto err2;
 
+	/* Allow the TV output to be overriden */
+	if (tv_connection) {
+		if (strcmp(tv_connection, "svideo") == 0) {
+			printk(KERN_INFO
+				"omapdss: tv output is svideo.\n");
+			dssdev->phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO;
+		} else if (strcmp(tv_connection, "composite") == 0) {
+			printk(KERN_INFO
+				"omapdss: tv output is composite.\n");
+			dssdev->phy.venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE;
+		} else {
+			printk(KERN_INFO
+				"omapdss: unsupported output type'%s'.\n",
+				tv_connection);
+		}
+	}
+
 	return 0;
 
 err2:
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index ca585ef..f3cfabb 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2028,7 +2028,15 @@ static int omapfb_mode_to_timings(const char *mode_str,
 	int r;
 
 #ifdef CONFIG_OMAP2_DSS_VENC
-	if (strcmp(mode_str, "pal") == 0) {
+	if (strcmp(mode_str, "pal-16") == 0) {
+		*timings = omap_dss_pal_timings;
+		*bpp = 16;
+		return 0;
+	} else if (strcmp(mode_str, "ntsc-16") == 0) {
+		*timings = omap_dss_ntsc_timings;
+		*bpp = 16;
+		return 0;
+	} else if (strcmp(mode_str, "pal") == 0) {
 		*timings = omap_dss_pal_timings;
 		*bpp = 24;
 		return 0;
diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
index 395cb6a..f47b59b 100644
--- a/drivers/video/ssd1307fb.c
+++ b/drivers/video/ssd1307fb.c
@@ -16,24 +16,50 @@
 #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_SET_ADDRESS_MODE	0x20
+#define SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL	(0x00)
+#define SSD1307FB_SET_ADDRESS_MODE_VERTICAL	(0x01)
+#define SSD1307FB_SET_ADDRESS_MODE_PAGE		(0x02)
+#define SSD1307FB_SET_COL_RANGE		0x21
+#define SSD1307FB_SET_PAGE_RANGE	0x22
 #define SSD1307FB_CONTRAST		0x81
+#define	SSD1307FB_CHARGE_PUMP		0x8d
 #define SSD1307FB_SEG_REMAP_ON		0xa1
 #define SSD1307FB_DISPLAY_OFF		0xae
+#define SSD1307FB_SET_MULTIPLEX_RATIO	0xa8
 #define SSD1307FB_DISPLAY_ON		0xaf
 #define SSD1307FB_START_PAGE_ADDRESS	0xb0
+#define SSD1307FB_SET_DISPLAY_OFFSET	0xd3
+#define	SSD1307FB_SET_CLOCK_FREQ	0xd5
+#define	SSD1307FB_SET_PRECHARGE_PERIOD	0xd9
+#define	SSD1307FB_SET_COM_PINS_CONFIG	0xda
+#define	SSD1307FB_SET_VCOMH		0xdb
+
+struct ssd1307fb_par;
+
+struct ssd1307fb_ops {
+	int (*init)(struct ssd1307fb_par *);
+	int (*remove)(struct ssd1307fb_par *);
+};
 
 struct ssd1307fb_par {
 	struct i2c_client *client;
+	u32 height;
 	struct fb_info *info;
+	struct ssd1307fb_ops *ops;
+	u32 page_offset;
 	struct pwm_device *pwm;
 	u32 pwm_period;
 	int reset;
+	u32 width;
+};
+
+struct ssd1307fb_array {
+	u8	type;
+	u8	data[0];
 };
 
 static struct fb_fix_screeninfo ssd1307fb_fix = {
@@ -43,65 +69,64 @@ static struct fb_fix_screeninfo ssd1307fb_fix = {
 	.xpanstep	= 0,
 	.ypanstep	= 0,
 	.ywrapstep	= 0,
-	.line_length	= SSD1307FB_WIDTH / 8,
 	.accel		= FB_ACCEL_NONE,
 };
 
 static struct fb_var_screeninfo ssd1307fb_var = {
-	.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)
+static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8 type)
 {
-	u8 *buf;
-	int ret = 0;
+	struct ssd1307fb_array *array = kzalloc(sizeof(struct ssd1307fb_array) + len, GFP_KERNEL);
+	if (!array)
+		return NULL;
 
-	buf = kzalloc(len + 1, GFP_KERNEL);
-	if (!buf) {
-		dev_err(&client->dev, "Couldn't allocate sending buffer.\n");
-		return -ENOMEM;
-	}
+	array->type = type;
 
-	buf[0] = type;
-	memcpy(buf + 1, cmd, len);
+	return array;
+}
+
+static int ssd1307fb_write_array(struct i2c_client *client, struct ssd1307fb_array *array, u32 len)
+{
+	int ret;
 
-	ret = i2c_master_send(client, buf, len + 1);
-	if (ret != len + 1) {
+	len += sizeof(struct ssd1307fb_array);
+
+	ret = i2c_master_send(client, (u8*)array, len);
+	if (ret != len) {
 		dev_err(&client->dev, "Couldn't send I2C command.\n");
-		goto error;
+		return ret;
 	}
 
-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);
+	return 0;
 }
 
 static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
 {
-	return ssd1307fb_write_cmd_array(client, &cmd, 1);
-}
+	struct ssd1307fb_array *array = ssd1307fb_alloc_array(1, SSD1307FB_COMMAND);
+	if (!array)
+		return -ENOMEM;
 
-static inline int ssd1307fb_write_data_array(struct i2c_client *client, u8 *cmd, u32 len)
-{
-	return ssd1307fb_write_array(client, SSD1307FB_DATA, cmd, len);
+	array->data[0] = cmd;
+
+	return ssd1307fb_write_array(client, array, 1);
 }
 
 static inline int ssd1307fb_write_data(struct i2c_client *client, u8 data)
 {
-	return ssd1307fb_write_data_array(client, &data, 1);
+	struct ssd1307fb_array *array = ssd1307fb_alloc_array(1, SSD1307FB_DATA);
+	if (!array)
+		return -ENOMEM;
+
+	array->data[0] = data;
+
+	return ssd1307fb_write_array(client, array, 1);
 }
 
 static void ssd1307fb_update_display(struct ssd1307fb_par *par)
 {
+	struct ssd1307fb_array *array = ssd1307fb_alloc_array(par->width * par->height / 8, SSD1307FB_DATA);
 	u8 *vmem = par->info->screen_base;
 	int i, j, k;
 
@@ -134,24 +159,21 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
 	 *  (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 (i = 0; i < (par->height / 8); i++) {
+		for (j = 0; j < par->width; j++) {
+			u32 array_idx = i * par->width + j;
+			array->data[array_idx] = 0;
 			for (k = 0; k < 8; k++) {
-				u32 page_length = SSD1307FB_WIDTH * i;
-				u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8;
+				u32 page_length = par->width * i;
+				u32 index = page_length + (par->width * k + j) / 8;
 				u8 byte = *(vmem + index);
 				u8 bit = byte & (1 << (j % 8));
 				bit = bit >> (j % 8);
-				buf |= bit << k;
+				array->data[array_idx] |= bit << k;
 			}
-			ssd1307fb_write_data(par->client, buf);
 		}
 	}
+	ssd1307fb_write_array(par->client, array, par->width * par->height / 8);
 }
 
 
@@ -223,20 +245,159 @@ static void ssd1307fb_deferred_io(struct fb_info *info,
 }
 
 static struct fb_deferred_io ssd1307fb_defio = {
-	.delay		= HZ,
+	.delay		= HZ/8,
 	.deferred_io	= ssd1307fb_deferred_io,
 };
 
+static int ssd1307fb_ssd1307_init(struct ssd1307fb_par *par) {
+	int ret;
+
+	par->pwm = pwm_get(&par->client->dev, NULL);
+	if (IS_ERR(par->pwm)) {
+		dev_err(&par->client->dev, "Could not get PWM from device tree!\n");
+		return PTR_ERR(par->pwm);
+	}
+
+	par->pwm_period = pwm_get_period(par->pwm);
+	/* Enable the PWM */
+	pwm_config(par->pwm, par->pwm_period / 2, par->pwm_period);
+	pwm_enable(par->pwm);
+
+	dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n", par->pwm->pwm, par->pwm_period);
+
+	/* Map column 127 of the OLED to segment 0 */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+	if (ret < 0)
+		return ret;
+
+	/* Turn on the display */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int ssd1307fb_ssd1307_remove(struct ssd1307fb_par *par) {
+	pwm_disable(par->pwm);
+	pwm_put(par->pwm);
+	return 0;
+}
+
+static struct ssd1307fb_ops ssd1307fb_ssd1307_ops = {
+	.init	= ssd1307fb_ssd1307_init,
+	.remove	= ssd1307fb_ssd1307_remove,
+};
+
+static int ssd1307fb_ssd1306_init(struct ssd1307fb_par *par) {
+	int ret;
+
+	/* Set initial contrast */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x7f);
+	if (ret < 0)
+		return ret;
+
+	/* Set COM direction */
+	ret = ssd1307fb_write_cmd(par->client, 0xc8);
+	if (ret < 0)
+		return ret;
+
+	/* Set segment re-map */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON);
+	if (ret < 0)
+		return ret;
+
+	/* Set multiplex ratio value */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_MULTIPLEX_RATIO);
+	ret = ret & ssd1307fb_write_cmd(par->client, par->height - 1);
+	if (ret < 0)
+		return ret;
+
+	/* set display offset value */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_DISPLAY_OFFSET);
+	ret = ssd1307fb_write_cmd(par->client, 0x20);
+	if (ret < 0)
+		return ret;
+
+	/* Set clock frequency */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0xf0);
+	if (ret < 0)
+		return ret;
+
+	/* Set precharge period in number of ticks from the internal clock */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
+	if (ret < 0)
+		return ret;
+
+	/* Set COM pins configuration */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x22);
+	if (ret < 0)
+		return ret;
+
+	/* Set VCOMH */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_VCOMH);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x49);
+	if (ret < 0)
+		return ret;
+
+	/* Turn on the DC-DC Charge Pump */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x14);
+	if (ret < 0)
+		return ret;
+
+	/* Switch to horizontal addressing mode */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE);
+	ret = ret & ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL);
+	if (ret < 0)
+		return ret;
+
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
+	ret = ret & ssd1307fb_write_cmd(par->client, par->width - 1);
+	if (ret < 0)
+		return ret;
+
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
+	ret = ret & ssd1307fb_write_cmd(par->client, 0x0);
+	ret = ret & ssd1307fb_write_cmd(par->client, par->page_offset + (par->height / 8) - 1);
+	if (ret < 0)
+		return ret;
+
+	/* Turn on the display */
+	ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct ssd1307fb_ops ssd1307fb_ssd1306_ops = {
+	.init	= ssd1307fb_ssd1306_init,
+};
+
+static const struct of_device_id ssd1307fb_of_match[] = {
+	{ .compatible = "solomon,ssd1306fb-i2c", .data = (void*)&ssd1307fb_ssd1306_ops },
+	{ .compatible = "solomon,ssd1307fb-i2c", .data = (void*)&ssd1307fb_ssd1307_ops },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ssd1307fb_of_match);
+
 static int 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 device_node *node = client->dev.of_node;
+	u32 vmem_size;
 	struct ssd1307fb_par *par;
 	u8 *vmem;
 	int ret;
 
-	if (!client->dev.of_node) {
+	if (!node) {
 		dev_err(&client->dev, "No device tree data found!\n");
 		return -EINVAL;
 	}
@@ -247,6 +408,36 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		return -ENOMEM;
 	}
 
+	par = info->par;
+	par->info = info;
+	par->client = client;
+
+	par->ops = (struct ssd1307fb_ops*)of_match_device(ssd1307fb_of_match, &client->dev)->data;
+
+	par->reset = of_get_named_gpio(client->dev.of_node,
+					 "reset-gpios", 0);
+	if (!gpio_is_valid(par->reset)) {
+		ret = -EINVAL;
+		goto fb_alloc_error;
+	}
+
+	if (of_property_read_u32(node, "solomon,width", &par->width))
+		par->width = 96;
+
+	printk("Width\t%u\n", par->width);
+
+	if (of_property_read_u32(node, "solomon,height", &par->height))
+		par->width = 16;
+
+	printk("Height\t%u\n", par->height);
+
+	if (of_property_read_u32(node, "solomon,page-offset", &par->page_offset))
+		par->page_offset = 1;
+
+	printk("Offset\t%u\n", par->page_offset);
+
+	vmem_size = par->width * par->height / 8;
+
 	vmem = devm_kzalloc(&client->dev, vmem_size, GFP_KERNEL);
 	if (!vmem) {
 		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
@@ -256,9 +447,15 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
 	info->fbops = &ssd1307fb_ops;
 	info->fix = ssd1307fb_fix;
+	info->fix.line_length = par->width / 8;
 	info->fbdefio = &ssd1307fb_defio;
 
 	info->var = ssd1307fb_var;
+	info->var.xres = par->width;
+	info->var.xres_virtual = par->width;
+	info->var.yres = par->height;
+	info->var.yres_virtual = par->height;
+
 	info->var.red.length = 1;
 	info->var.red.offset = 0;
 	info->var.green.length = 1;
@@ -272,17 +469,6 @@ static int ssd1307fb_probe(struct i2c_client *client,
 
 	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");
@@ -293,23 +479,6 @@ static int ssd1307fb_probe(struct i2c_client *client,
 		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 */
@@ -318,34 +487,25 @@ static int ssd1307fb_probe(struct i2c_client *client,
 	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;
+	if (par->ops->init) {
+		ret = par->ops->init(par);
+		if (ret)
+			goto reset_oled_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;
+	ret = register_framebuffer(info);
+	if (ret) {
+		dev_err(&client->dev, "Couldn't register the framebuffer\n");
+		goto panel_init_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:
+panel_init_error:
+	if (par->ops->remove)
+		par->ops->remove(par);
 reset_oled_error:
 	fb_deferred_io_cleanup(info);
 fb_alloc_error:
@@ -359,8 +519,8 @@ static int ssd1307fb_remove(struct i2c_client *client)
 	struct ssd1307fb_par *par = info->par;
 
 	unregister_framebuffer(info);
-	pwm_disable(par->pwm);
-	pwm_put(par->pwm);
+	if (par->ops->remove)
+		par->ops->remove(par);
 	fb_deferred_io_cleanup(info);
 	framebuffer_release(info);
 
@@ -368,17 +528,12 @@ static int ssd1307fb_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ssd1307fb_i2c_id[] = {
+	{ "ssd1306fb", 0 },
 	{ "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 = ssd1307fb_remove,
diff --git a/drivers/video/st7735fb.c b/drivers/video/st7735fb.c
new file mode 100644
index 0000000..3a5c8a9
--- /dev/null
+++ b/drivers/video/st7735fb.c
@@ -0,0 +1,631 @@
+/*
+ * linux/drivers/video/st7735fb.c -- FB driver for ST7735 LCD controller
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ *
+ * Copyright (C) 2012, Matt Porter <matt@ohporter.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+
+#include "st7735fb.h"
+
+static struct st7735_function st7735_cfg_script[] = {
+	{ ST7735_START, ST7735_START},
+	{ ST7735_CMD, ST7735_SWRESET},
+	{ ST7735_DELAY, 150},
+	{ ST7735_CMD, ST7735_SLPOUT},
+	{ ST7735_DELAY, 500},
+	{ ST7735_CMD, ST7735_FRMCTR1},
+	{ ST7735_DATA, 0x01},
+	{ ST7735_DATA, 0x2c},
+	{ ST7735_DATA, 0x2d},
+	{ ST7735_CMD, ST7735_FRMCTR2},
+	{ ST7735_DATA, 0x01},
+	{ ST7735_DATA, 0x2c},
+	{ ST7735_DATA, 0x2d},
+	{ ST7735_CMD, ST7735_FRMCTR3},
+	{ ST7735_DATA, 0x01},
+	{ ST7735_DATA, 0x2c},
+	{ ST7735_DATA, 0x2d},
+	{ ST7735_DATA, 0x01},
+	{ ST7735_DATA, 0x2c},
+	{ ST7735_DATA, 0x2d},
+	{ ST7735_CMD, ST7735_INVCTR},
+	{ ST7735_DATA, 0x07},
+	{ ST7735_CMD, ST7735_PWCTR1},
+	{ ST7735_DATA, 0xa2},
+	{ ST7735_DATA, 0x02},
+	{ ST7735_DATA, 0x84},
+	{ ST7735_CMD, ST7735_PWCTR2},
+	{ ST7735_DATA, 0xc5},
+	{ ST7735_CMD, ST7735_PWCTR3},
+	{ ST7735_DATA, 0x0a},
+	{ ST7735_DATA, 0x00},
+	{ ST7735_CMD, ST7735_PWCTR4},
+	{ ST7735_DATA, 0x8a},
+	{ ST7735_DATA, 0x2a},
+	{ ST7735_CMD, ST7735_PWCTR5},
+	{ ST7735_DATA, 0x8a},
+	{ ST7735_DATA, 0xee},
+	{ ST7735_CMD, ST7735_VMCTR1},
+	{ ST7735_DATA, 0x0e},
+	{ ST7735_CMD, ST7735_INVOFF},
+	{ ST7735_CMD, ST7735_MADCTL},
+	{ ST7735_DATA, 0xc8},
+	{ ST7735_CMD, ST7735_COLMOD},
+	{ ST7735_DATA, 0x05},
+	{ ST7735_CMD, ST7735_CASET},
+	{ ST7735_DATA, 0x00},
+	{ ST7735_DATA, 0x00},
+	{ ST7735_DATA, 0x00},
+	{ ST7735_DATA, 0x00},
+	{ ST7735_DATA, 0x7f},
+	{ ST7735_CMD, ST7735_RASET},
+	{ ST7735_DATA, 0x00},
+	{ ST7735_DATA, 0x00},
+	{ ST7735_DATA, 0x00},
+	{ ST7735_DATA, 0x00},
+	{ ST7735_DATA, 0x9f},
+	{ ST7735_CMD, ST7735_GMCTRP1},
+	{ ST7735_DATA, 0x02},
+	{ ST7735_DATA, 0x1c},
+	{ ST7735_DATA, 0x07},
+	{ ST7735_DATA, 0x12},
+	{ ST7735_DATA, 0x37},
+	{ ST7735_DATA, 0x32},
+	{ ST7735_DATA, 0x29},
+	{ ST7735_DATA, 0x2d},
+	{ ST7735_DATA, 0x29},
+	{ ST7735_DATA, 0x25},
+	{ ST7735_DATA, 0x2b},
+	{ ST7735_DATA, 0x39},
+	{ ST7735_DATA, 0x00},
+	{ ST7735_DATA, 0x01},
+	{ ST7735_DATA, 0x03},
+	{ ST7735_DATA, 0x10},
+	{ ST7735_CMD, ST7735_GMCTRN1},
+	{ ST7735_DATA, 0x03},
+	{ ST7735_DATA, 0x1d},
+	{ ST7735_DATA, 0x07},
+	{ ST7735_DATA, 0x06},
+	{ ST7735_DATA, 0x2e},
+	{ ST7735_DATA, 0x2c},
+	{ ST7735_DATA, 0x29},
+	{ ST7735_DATA, 0x2d},
+	{ ST7735_DATA, 0x2e},
+	{ ST7735_DATA, 0x2e},
+	{ ST7735_DATA, 0x37},
+	{ ST7735_DATA, 0x3f},
+	{ ST7735_DATA, 0x00},
+	{ ST7735_DATA, 0x00},
+	{ ST7735_DATA, 0x02},
+	{ ST7735_DATA, 0x10},
+	{ ST7735_CMD, ST7735_DISPON},
+	{ ST7735_DELAY, 100},
+	{ ST7735_CMD, ST7735_NORON},
+	{ ST7735_DELAY, 10},
+	{ ST7735_END, ST7735_END},
+};
+
+static struct fb_fix_screeninfo st7735fb_fix = {
+	.id =		"ST7735", 
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_DIRECTCOLOR,
+	.xpanstep =	0,
+	.ypanstep =	0,
+	.ywrapstep =	0, 
+	.line_length =	WIDTH*BPP/8,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo st7735fb_var = {
+	.xres =			WIDTH,
+	.yres =			HEIGHT,
+	.xres_virtual =		WIDTH,
+	.yres_virtual =		HEIGHT,
+	.bits_per_pixel =	BPP,
+	.nonstd	=		0,
+};
+
+static int st7735_write(struct st7735fb_par *par, u8 data)
+{
+	par->buf[0] = data;
+
+	return spi_write(par->spi, par->buf, 1);
+}
+
+static void st7735_write_data(struct st7735fb_par *par, u8 data)
+{
+	int ret = 0;
+
+	/* Set data mode */
+	gpio_set_value(par->dc, 1);
+
+	ret = st7735_write(par, data);
+	if (ret < 0)
+		pr_err("%s: write data %02x failed with status %d\n",
+			par->info->fix.id, data, ret);
+}
+
+static int st7735_write_data_buf(struct st7735fb_par *par,
+					u8 *txbuf, int size)
+{
+	/* Set data mode */
+	gpio_set_value(par->dc, 1);
+
+	/* Write entire buffer */
+	return spi_write(par->spi, txbuf, size);
+}
+
+static void st7735_write_cmd(struct st7735fb_par *par, u8 data)
+{
+	int ret = 0;
+
+	/* Set command mode */
+	gpio_set_value(par->dc, 0);
+
+	ret = st7735_write(par, data);
+	if (ret < 0)
+		pr_err("%s: write command %02x failed with status %d\n",
+			par->info->fix.id, data, ret);
+}
+
+static void st7735_run_cfg_script(struct st7735fb_par *par)
+{
+	int i = 0;
+	int end_script = 0;
+
+	do {
+		switch (st7735_cfg_script[i].cmd)
+		{
+		case ST7735_START:
+			break;
+		case ST7735_CMD:
+			st7735_write_cmd(par,
+				st7735_cfg_script[i].data & 0xff);
+			break;
+		case ST7735_DATA:
+			st7735_write_data(par,
+				st7735_cfg_script[i].data & 0xff);
+			break;
+		case ST7735_DELAY:
+			mdelay(st7735_cfg_script[i].data);
+			break;
+		case ST7735_END:
+			end_script = 1;
+		}
+		i++;
+	} while (!end_script);
+}
+
+static void st7735_set_addr_win(struct st7735fb_par *par,
+				int xs, int ys, int xe, int ye)
+{
+	st7735_write_cmd(par, ST7735_CASET);
+	st7735_write_data(par, 0x00);
+	st7735_write_data(par, xs + par->xoff);
+	st7735_write_data(par, 0x00);
+	st7735_write_data(par, xe + par->xoff);
+	st7735_write_cmd(par, ST7735_RASET);
+	st7735_write_data(par, 0x00);
+	st7735_write_data(par, ys + par->yoff);
+	st7735_write_data(par, 0x00);
+	st7735_write_data(par, ye + par->yoff);
+}
+
+static void st7735_reset(struct st7735fb_par *par)
+{
+	/* Reset controller */
+	gpio_set_value(par->rst, 0);
+	udelay(10);
+	gpio_set_value(par->rst, 1);
+	mdelay(120);
+}
+
+static void st7735fb_update_display(struct st7735fb_par *par)
+{
+	int ret = 0;
+	u16 *vmem;
+#ifdef __LITTLE_ENDIAN
+	int i;
+	u16 *vmem16 = (u16 *)par->info->screen_base;
+	vmem = par->ssbuf;
+
+	for (i=0; i<WIDTH*HEIGHT*BPP/8/2; i++)
+		vmem[i] = swab16(vmem16[i]);
+#else
+	vmem = (u16 *)par->info->screen_base;
+#endif
+
+	mutex_lock(&(par->io_lock));
+
+	/* Set row/column data window */
+	st7735_set_addr_win(par, 0, 0, WIDTH-1, HEIGHT-1);
+
+	/* Internal RAM write command */
+	st7735_write_cmd(par, ST7735_RAMWR);
+
+	/* Blast framebuffer to ST7735 internal display RAM */
+	ret = st7735_write_data_buf(par, (u8 *)vmem, WIDTH*HEIGHT*BPP/8);
+	if (ret < 0)
+		pr_err("%s: spi_write failed to update display buffer\n",
+			par->info->fix.id);
+
+	mutex_unlock(&(par->io_lock));
+}
+
+static int st7735fb_init_display(struct st7735fb_par *par)
+{
+	int ret = 0;
+
+        /* Request GPIOs and initialize to default values */
+        ret = gpio_request_one(par->rst, GPIOF_OUT_INIT_HIGH,
+			"ST7735 Reset Pin");
+	if (ret < 0) {
+		pr_err("%s: failed to claim reset pin\n", par->info->fix.id);
+		goto out;
+	}
+        ret = gpio_request_one(par->dc, GPIOF_OUT_INIT_LOW,
+			"ST7735 Data/Command Pin");
+	if (ret < 0) {
+		pr_err("%s: failed to claim data/command pin\n", par->info->fix.id);
+		goto out;
+	}
+
+	st7735_reset(par);
+
+	st7735_run_cfg_script(par);
+
+out:
+	return ret;
+}
+
+static void st7735fb_deferred_io(struct fb_info *info,
+				struct list_head *pagelist)
+{
+	st7735fb_update_display(info->par);
+}
+
+static void st7735fb_update_display_deferred(struct fb_info *info)
+{
+	struct fb_deferred_io *fbdefio = info->fbdefio;
+
+	schedule_delayed_work(&info->deferred_work, fbdefio->delay);
+}
+
+static void st7735fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	sys_fillrect(info, rect);
+
+	st7735fb_update_display_deferred(info);
+}
+
+static void st7735fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 
+{
+	sys_copyarea(info, area);
+
+	st7735fb_update_display_deferred(info);
+}
+
+static void st7735fb_imageblit(struct fb_info *info, const struct fb_image *image) 
+{
+	sys_imageblit(info, image);
+
+	st7735fb_update_display_deferred(info);
+}
+
+static ssize_t st7735fb_write(struct fb_info *info, const char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	unsigned long p = *ppos;
+	void *dst;
+	int err = 0;
+	unsigned long total_size;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return -EPERM;
+
+	total_size = info->fix.smem_len;
+
+	if (p > total_size)
+		return -EFBIG;
+
+	if (count > total_size) {
+		err = -EFBIG;
+		count = total_size;
+	}
+
+	if (count + p > total_size) {
+		if (!err)
+			err = -ENOSPC;
+
+		count = total_size - p;
+	}
+
+	dst = (void __force *) (info->screen_base + p);
+
+	if (copy_from_user(dst, buf, count))
+		err = -EFAULT;
+
+	if  (!err)
+		*ppos += count;
+
+	st7735fb_update_display_deferred(info);
+
+	return (err) ? err : count;
+}
+
+static int st7735fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+				unsigned blue, unsigned transp,
+				struct fb_info *info)
+{
+	if (regno >= MAX_PALETTE)
+		return -EINVAL;
+
+	/* RGB565 */
+	((u32*)(info->pseudo_palette))[regno] =
+		((red & 0xf800) |
+		((green & 0xfc00) >> 5) |
+		((blue & 0xf800) >> 11));
+
+	return 0;
+}
+
+static struct fb_ops st7735fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_read	= fb_sys_read,
+	.fb_write	= st7735fb_write,
+	.fb_fillrect	= st7735fb_fillrect,
+	.fb_copyarea	= st7735fb_copyarea,
+	.fb_imageblit	= st7735fb_imageblit,
+	.fb_setcolreg	= st7735fb_setcolreg,
+};
+
+static struct fb_deferred_io st7735fb_defio = {
+	.delay		= HZ/20,
+	.deferred_io	= st7735fb_deferred_io,
+};
+
+static const struct spi_device_id st7735fb_device_id[] = {
+	{
+		.name = "tft-lcd-1.8-green",
+		.driver_data = ST7735_AF_TFT18_GREEN,
+	}, {
+		.name = "tft-lcd-1.8-red",
+		.driver_data = ST7735_AF_TFT18_RED,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(spi, st7735fb_device_id);
+
+static const struct of_device_id st7735fb_dt_ids[] = {
+	{ .compatible = "adafruit,tft-lcd-1.8-green", .data = (void *) ST7735_AF_TFT18_GREEN, },
+	{ .compatible = "adafruit,tft-lcd-1.8-red", .data = (void *) ST7735_AF_TFT18_RED, },
+};
+MODULE_DEVICE_TABLE(of, st7735fb_dt_ids);
+
+static int st7735fb_probe (struct spi_device *spi)
+{
+	int vmem_size = WIDTH*HEIGHT*BPP/8;
+	u8 *vmem;
+	struct fb_info *info;
+	struct st7735fb_par *par;
+	int retval = -ENOMEM;
+	struct device_node *np = spi->dev.of_node;
+	const struct spi_device_id *spi_id = spi_get_device_id(spi);
+	struct pinctrl *pinctrl;
+
+	if (!spi_id) {
+		dev_err(&spi->dev,
+			"device id not supported!\n");
+		return -EINVAL;
+	}
+
+	pinctrl = devm_pinctrl_get_select_default(&spi->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&spi->dev,
+			"pins are not configured from the driver\n");
+
+#ifdef __LITTLE_ENDIAN
+	vmem = (u8 *)vmalloc(vmem_size);
+#else
+	vmem = (u8 *)kmalloc(vmem_size, GFP_KERNEL);
+#endif
+	if (!vmem)
+		return retval;
+
+	info = framebuffer_alloc(sizeof(struct st7735fb_par), &spi->dev);
+	if (!info)
+		goto fballoc_fail;
+
+	info->pseudo_palette = kmalloc(sizeof(u32)*MAX_PALETTE, GFP_KERNEL);
+	if (!info->pseudo_palette) {
+		goto palette_fail;
+	}
+
+	info->screen_base = (u8 __force __iomem *)vmem;
+	info->fbops = &st7735fb_ops;
+	info->fix = st7735fb_fix;
+	info->fix.smem_len = vmem_size;
+	info->var = st7735fb_var;
+	/* Choose any packed pixel format as long as it's RGB565 */
+	info->var.red.offset = 11;
+	info->var.red.length = 5;
+	info->var.green.offset = 5;
+	info->var.green.length = 6;
+	info->var.blue.offset = 0;
+	info->var.blue.length = 5;
+	info->var.transp.offset = 0;
+	info->var.transp.length = 0;
+	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
+
+	info->fbdefio = &st7735fb_defio;
+	fb_deferred_io_init(info);
+
+	retval = fb_alloc_cmap(&info->cmap, MAX_PALETTE, 0);
+	if (retval < 0)
+		goto cmap_fail;
+	info->cmap.len = MAX_PALETTE;
+
+	par = info->par;
+	par->info = info;
+	par->spi = spi;
+
+	mutex_init(&par->io_lock);
+
+	if (spi_id->driver_data == ST7735_AF_TFT18_GREEN) {
+		par->xoff = 2;
+		par->yoff = 1;
+	} else {
+		par->xoff = 0;
+		par->yoff = 0;
+	}
+
+	/* TODO: fix all exit paths for cleanup */
+        par->rst = of_get_named_gpio(np, "st7735-rst", 0);
+	if (par->rst < 0) {
+		printk("failed to find st7735-rst node!\n");
+		return -EINVAL;
+	}
+
+        par->dc = of_get_named_gpio(np, "st7735-dc", 0);
+	if (par->dc < 0) {
+		printk("failed to find st7735-dc node!\n");
+		return -EINVAL;
+	}
+
+	par->buf = kmalloc(1, GFP_KERNEL);
+	if (!par->buf) {
+		retval = -ENOMEM;
+		goto buf_fail;
+	}
+
+#ifdef __LITTLE_ENDIAN
+	/* Allocated swapped shadow buffer */
+	par->ssbuf = kmalloc(vmem_size, GFP_KERNEL);
+	if (!par->ssbuf) {
+		retval = -ENOMEM;
+		goto ssbuf_fail;
+	}
+#endif
+
+	retval = st7735fb_init_display(par);
+	if (retval < 0)
+		goto init_fail;
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto fbreg_fail;
+
+	spi_set_drvdata(spi, info);
+
+	printk(KERN_INFO
+		"fb%d: %s frame buffer device,\n\tusing %d KiB of video memory\n",
+		info->node, info->fix.id, vmem_size);
+
+	return 0;
+
+
+	spi_set_drvdata(spi, NULL);
+
+fbreg_fail:
+	/* TODO: release gpios on fail */
+	/* TODO: and unwind everything in init */
+
+init_fail:
+#ifdef __LITTLE_ENDIAN
+	kfree(par->ssbuf);
+#endif
+
+ssbuf_fail:
+	kfree(par->buf);
+
+buf_fail:
+	fb_dealloc_cmap(&info->cmap);
+
+cmap_fail:
+	kfree(info->pseudo_palette);
+
+palette_fail:
+	framebuffer_release(info);
+
+fballoc_fail:
+#ifdef __LITTLE_ENDIAN
+	vfree(vmem);
+#else
+	kfree(vmem);
+#endif
+
+	return retval;
+}
+
+static int st7735fb_remove(struct spi_device *spi)
+{
+	struct fb_info *info = spi_get_drvdata(spi);
+
+	spi_set_drvdata(spi, NULL);
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		kfree(info->pseudo_palette);
+		vfree(info->screen_base);	
+		framebuffer_release(info);
+	}
+
+	/* TODO: release gpios */
+
+	return 0;
+}
+
+static struct spi_driver st7735fb_driver = {
+	.id_table = st7735fb_device_id,
+	.driver = {
+		.name   = "st7735",
+		.owner  = THIS_MODULE,
+		.of_match_table = st7735fb_dt_ids,
+	},
+	.probe  = st7735fb_probe,
+	.remove = st7735fb_remove,
+};
+
+static int __init st7735fb_init(void)
+{
+	return spi_register_driver(&st7735fb_driver);
+}
+
+static void __exit st7735fb_exit(void)
+{
+	spi_unregister_driver(&st7735fb_driver);
+}
+
+/* ------------------------------------------------------------------------- */
+
+module_init(st7735fb_init);
+module_exit(st7735fb_exit);
+
+MODULE_DESCRIPTION("FB driver for ST7735 display controller");
+MODULE_AUTHOR("Matt Porter <matt@ohporter.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/st7735fb.h b/drivers/video/st7735fb.h
new file mode 100644
index 0000000..0ce5c11
--- /dev/null
+++ b/drivers/video/st7735fb.h
@@ -0,0 +1,84 @@
+/*
+ * linux/include/video/st7735fb.h -- FB driver for ST7735 LCD controller
+ *
+ * Copyright (C) 2012, Matt Porter
+ *
+ * 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.
+ */
+
+#define DRVNAME		"st7735fb"
+#define WIDTH		128
+#define HEIGHT		160
+#define BPP		16
+#define MAX_PALETTE	16
+
+/* Supported display modules */
+#define ST7735_AF_TFT18_GREEN		0	/* Adafruit SPI TFT 1.8" - green tab */
+#define ST7735_AF_TFT18_RED		1	/* Adafruit SPI TFT 1.8" - red tab */
+
+/* Init script function */
+struct st7735_function {
+	u16 cmd;
+	u16 data;
+};
+
+/* Init script commands */
+enum st7735_cmd {
+	ST7735_START,
+	ST7735_END,
+	ST7735_CMD,
+	ST7735_DATA,
+	ST7735_DELAY
+};
+
+struct st7735fb_par {
+	struct spi_device *spi;
+	struct fb_info *info;
+	struct mutex io_lock;
+	int xoff;
+	int yoff;
+	int rst;
+	int dc;
+	u16 *ssbuf;
+	u8 *buf;
+};
+
+/* ST7735 Commands */
+#define ST7735_NOP	0x0
+#define ST7735_SWRESET	0x01
+#define ST7735_RDDID	0x04
+#define ST7735_RDDST	0x09
+#define ST7735_SLPIN	0x10
+#define ST7735_SLPOUT	0x11
+#define ST7735_PTLON	0x12
+#define ST7735_NORON	0x13
+#define ST7735_INVOFF	0x20
+#define ST7735_INVON	0x21
+#define ST7735_DISPOFF	0x28
+#define ST7735_DISPON	0x29
+#define ST7735_CASET	0x2A
+#define ST7735_RASET	0x2B
+#define ST7735_RAMWR	0x2C
+#define ST7735_RAMRD	0x2E
+#define ST7735_COLMOD	0x3A
+#define ST7735_MADCTL	0x36
+#define ST7735_FRMCTR1	0xB1
+#define ST7735_FRMCTR2	0xB2
+#define ST7735_FRMCTR3	0xB3
+#define ST7735_INVCTR	0xB4
+#define ST7735_DISSET5	0xB6
+#define ST7735_PWCTR1	0xC0
+#define ST7735_PWCTR2	0xC1
+#define ST7735_PWCTR3	0xC2
+#define ST7735_PWCTR4	0xC3
+#define ST7735_PWCTR5	0xC4
+#define ST7735_VMCTR1	0xC5
+#define ST7735_RDID1	0xDA
+#define ST7735_RDID2	0xDB
+#define ST7735_RDID3	0xDC
+#define ST7735_RDID4	0xDD
+#define ST7735_GMCTRP1	0xE0
+#define ST7735_GMCTRN1	0xE1
+#define ST7735_PWCTR6	0xFC
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 80233da..22450908 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -1467,10 +1467,10 @@ void viafb_set_vclock(u32 clk, int set_iga)
 	via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
 }
 
-struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
+struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
 	u16 cxres, u16 cyres)
 {
-	struct display_timing timing;
+	struct via_display_timing timing;
 	u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2;
 
 	timing.hor_addr = cxres;
@@ -1491,7 +1491,7 @@ struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
 void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
 	u16 cxres, u16 cyres, int iga)
 {
-	struct display_timing crt_reg = var_to_timing(var,
+	struct via_display_timing crt_reg = var_to_timing(var,
 		cxres ? cxres : var->xres, cyres ? cyres : var->yres);
 
 	if (iga == IGA1)
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index a820575..3be073c 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -637,7 +637,7 @@ extern int viafb_LCD_ON;
 extern int viafb_DVI_ON;
 extern int viafb_hotplug;
 
-struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
+struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
 	u16 cxres, u16 cyres);
 void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
 	u16 cxres, u16 cyres, int iga);
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index 980ee1b..5d21ff4 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -549,7 +549,7 @@ void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
 	int panel_hres = plvds_setting_info->lcd_panel_hres;
 	int panel_vres = plvds_setting_info->lcd_panel_vres;
 	u32 clock;
-	struct display_timing timing;
+	struct via_display_timing timing;
 	struct fb_var_screeninfo panel_var;
 	const struct fb_videomode *mode_crt_table, *panel_crt_table;
 
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 3158dfc..65c65c6 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -319,7 +319,7 @@ struct crt_mode_table {
 	int refresh_rate;
 	int h_sync_polarity;
 	int v_sync_polarity;
-	struct display_timing crtc;
+	struct via_display_timing crtc;
 };
 
 struct io_reg {
diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c
index 0e431ae..0b414b0 100644
--- a/drivers/video/via/via_modesetting.c
+++ b/drivers/video/via/via_modesetting.c
@@ -30,9 +30,9 @@
 #include "debug.h"
 
 
-void via_set_primary_timing(const struct display_timing *timing)
+void via_set_primary_timing(const struct via_display_timing *timing)
 {
-	struct display_timing raw;
+	struct via_display_timing raw;
 
 	raw.hor_total = timing->hor_total / 8 - 5;
 	raw.hor_addr = timing->hor_addr / 8 - 1;
@@ -88,9 +88,9 @@ void via_set_primary_timing(const struct display_timing *timing)
 	via_write_reg_mask(VIACR, 0x17, 0x80, 0x80);
 }
 
-void via_set_secondary_timing(const struct display_timing *timing)
+void via_set_secondary_timing(const struct via_display_timing *timing)
 {
-	struct display_timing raw;
+	struct via_display_timing raw;
 
 	raw.hor_total = timing->hor_total - 1;
 	raw.hor_addr = timing->hor_addr - 1;
diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h
index 06e09fe..f6a6503 100644
--- a/drivers/video/via/via_modesetting.h
+++ b/drivers/video/via/via_modesetting.h
@@ -33,7 +33,7 @@
 #define VIA_PITCH_MAX	0x3FF8
 
 
-struct display_timing {
+struct via_display_timing {
 	u16 hor_total;
 	u16 hor_addr;
 	u16 hor_blank_start;
@@ -49,8 +49,8 @@ struct display_timing {
 };
 
 
-void via_set_primary_timing(const struct display_timing *timing);
-void via_set_secondary_timing(const struct display_timing *timing);
+void via_set_primary_timing(const struct via_display_timing *timing);
+void via_set_secondary_timing(const struct via_display_timing *timing);
 void via_set_primary_address(u32 addr);
 void via_set_secondary_address(u32 addr);
 void via_set_primary_pitch(u32 pitch);
diff --git a/drivers/video/videomode.c b/drivers/video/videomode.c
new file mode 100644
index 0000000..21c47a2
--- /dev/null
+++ b/drivers/video/videomode.c
@@ -0,0 +1,39 @@
+/*
+ * generic display timing functions
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * This file is released under the GPLv2
+ */
+
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <video/display_timing.h>
+#include <video/videomode.h>
+
+int videomode_from_timing(const struct display_timings *disp,
+			  struct videomode *vm, unsigned int index)
+{
+	struct display_timing *dt;
+
+	dt = display_timings_get(disp, index);
+	if (!dt)
+		return -EINVAL;
+
+	vm->pixelclock = display_timing_get_value(&dt->pixelclock, TE_TYP);
+	vm->hactive = display_timing_get_value(&dt->hactive, TE_TYP);
+	vm->hfront_porch = display_timing_get_value(&dt->hfront_porch, TE_TYP);
+	vm->hback_porch = display_timing_get_value(&dt->hback_porch, TE_TYP);
+	vm->hsync_len = display_timing_get_value(&dt->hsync_len, TE_TYP);
+
+	vm->vactive = display_timing_get_value(&dt->vactive, TE_TYP);
+	vm->vfront_porch = display_timing_get_value(&dt->vfront_porch, TE_TYP);
+	vm->vback_porch = display_timing_get_value(&dt->vback_porch, TE_TYP);
+	vm->vsync_len = display_timing_get_value(&dt->vsync_len, TE_TYP);
+
+	vm->dmt_flags = dt->dmt_flags;
+	vm->data_flags = dt->data_flags;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(videomode_from_timing);
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index 012817a..464b1a8 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -47,31 +47,46 @@ 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" },
 	{}
 };
 MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
 
-static int w1_gpio_probe_dt(struct platform_device *pdev)
+static struct w1_gpio_platform_data *
+w1_gpio_probe_dt(struct platform_device *pdev)
 {
-	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+	struct w1_gpio_platform_data *pdata;
 	struct device_node *np = pdev->dev.of_node;
 
+	if (!np)
+		return ERR_PTR(-ENOENT);
+
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	if (of_get_property(np, "linux,open-drain", NULL))
 		pdata->is_open_drain = 1;
 
 	pdata->pin = of_get_gpio(np, 0);
 	pdata->ext_pullup_enable_pin = of_get_gpio(np, 1);
-	pdev->dev.platform_data = pdata;
 
-	return 0;
+	return pdata;
+}
+
+#else
+
+static inline struct w1_gpio_platform_data *
+w1_gpio_probe_dt(struct platform_device *pdev)
+{
+	return NULL;
 }
 
+#endif
+
 static int w1_gpio_probe(struct platform_device *pdev)
 {
 	struct w1_bus_master *master;
@@ -83,40 +98,40 @@ static int w1_gpio_probe(struct platform_device *pdev)
 	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;
+	pdata = dev_get_platdata(&pdev->dev);
+	if (!pdata)
+		pdata = w1_gpio_probe_dt(pdev);
 
 	if (!pdata) {
 		dev_err(&pdev->dev, "No configuration data\n");
 		return -ENXIO;
+	} else if (IS_ERR(pdata)) {
+		err = PTR_ERR(pdata);
+		dev_err(&pdev->dev, "Failed to parse DT\n");
+		return err;
 	}
 
-	master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL);
+	master = devm_kzalloc(&pdev->dev,
+			      sizeof(struct w1_bus_master), GFP_KERNEL);
 	if (!master) {
 		dev_err(&pdev->dev, "Out of memory\n");
 		return -ENOMEM;
 	}
 
-	err = gpio_request(pdata->pin, "w1");
+	err = devm_gpio_request(&pdev->dev, pdata->pin, "w1");
 	if (err) {
 		dev_err(&pdev->dev, "gpio_request (pin) failed\n");
-		goto free_master;
+		return err;
 	}
 
 	if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
-		err = gpio_request_one(pdata->ext_pullup_enable_pin,
-				       GPIOF_INIT_LOW, "w1 pullup");
+		err = devm_gpio_request_one(&pdev->dev,
+					    pdata->ext_pullup_enable_pin,
+					    GPIOF_INIT_LOW, "w1 pullup");
 		if (err < 0) {
-			dev_err(&pdev->dev, "gpio_request_one "
-					"(ext_pullup_enable_pin) failed\n");
-			goto free_gpio;
+			dev_err(&pdev->dev,
+				"gpio_request_one (ext_pullup_enable_pin) failed\n");
+			return err;
 		}
 	}
 
@@ -134,7 +149,7 @@ static int w1_gpio_probe(struct platform_device *pdev)
 	err = w1_add_master_device(master);
 	if (err) {
 		dev_err(&pdev->dev, "w1_add_master device failed\n");
-		goto free_gpio_ext_pu;
+		return err;
 	}
 
 	if (pdata->enable_external_pullup)
@@ -146,22 +161,12 @@ static int w1_gpio_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, master);
 
 	return 0;
-
- free_gpio_ext_pu:
-	if (gpio_is_valid(pdata->ext_pullup_enable_pin))
-		gpio_free(pdata->ext_pullup_enable_pin);
- free_gpio:
-	gpio_free(pdata->pin);
- free_master:
-	kfree(master);
-
-	return err;
 }
 
 static int w1_gpio_remove(struct platform_device *pdev)
 {
 	struct w1_bus_master *master = platform_get_drvdata(pdev);
-	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+	const struct w1_gpio_platform_data *pdata = master->data;
 
 	if (pdata->enable_external_pullup)
 		pdata->enable_external_pullup(0);
@@ -170,17 +175,16 @@ static int w1_gpio_remove(struct platform_device *pdev)
 		gpio_set_value(pdata->ext_pullup_enable_pin, 0);
 
 	w1_remove_master_device(master);
-	gpio_free(pdata->pin);
-	kfree(master);
 
 	return 0;
 }
 
-#ifdef CONFIG_PM
-
-static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int w1_gpio_suspend(struct device *dev)
 {
-	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct w1_bus_master *master = platform_get_drvdata(pdev);
+	const struct w1_gpio_platform_data *pdata = master->data;
 
 	if (pdata->enable_external_pullup)
 		pdata->enable_external_pullup(0);
@@ -188,31 +192,30 @@ static int w1_gpio_suspend(struct platform_device *pdev, pm_message_t state)
 	return 0;
 }
 
-static int w1_gpio_resume(struct platform_device *pdev)
+static int w1_gpio_resume(struct device *dev)
 {
-	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct w1_bus_master *master = platform_get_drvdata(pdev);
+	const struct w1_gpio_platform_data *pdata = master->data;
 
 	if (pdata->enable_external_pullup)
 		pdata->enable_external_pullup(1);
 
 	return 0;
 }
-
-#else
-#define w1_gpio_suspend	NULL
-#define w1_gpio_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(w1_gpio_pm_ops, w1_gpio_suspend, w1_gpio_resume);
+
 static struct platform_driver w1_gpio_driver = {
 	.driver = {
 		.name	= "w1-gpio",
 		.owner	= THIS_MODULE,
+		.pm	= &w1_gpio_pm_ops,
 		.of_match_table = of_match_ptr(w1_gpio_dt_ids),
 	},
 	.probe = w1_gpio_probe,
-	.remove	= w1_gpio_remove,
-	.suspend = w1_gpio_suspend,
-	.resume = w1_gpio_resume,
+	.remove = w1_gpio_remove,
 };
 
 module_platform_driver(w1_gpio_driver);
diff --git a/firmware/.gitignore b/firmware/.gitignore
index d9c6901..21e3640 100644
--- a/firmware/.gitignore
+++ b/firmware/.gitignore
@@ -4,3 +4,4 @@
 *.csp
 *.dsp
 ihex2fw
+*.dtbo
diff --git a/firmware/Makefile b/firmware/Makefile
index cbb09ce..0de40d98 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -136,6 +136,102 @@ fw-shipped-$(CONFIG_USB_VICAM) += vicam/firmware.fw
 fw-shipped-$(CONFIG_VIDEO_CPIA2) += cpia2/stv0672_vp4.bin
 fw-shipped-$(CONFIG_YAM) += yam/1200.bin yam/9600.bin
 
+# all the generic capes
+fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+	cape-bone-2g-emmc1.dtbo \
+	cape-bone-adafruit-lcd-00A0.dtbo \
+	cape-bone-adafruit-rtc-00A0.dtbo \
+	cape-bone-dvi-00A0.dtbo \
+	cape-bone-dvi-00A1.dtbo \
+	cape-bone-dvi-00A2.dtbo \
+	cape-bone-hexy-00A0.dtbo \
+	cape-bone-lcd3-00A0.dtbo \
+	cape-bone-lcd3-00A2.dtbo \
+	BB-BONE-AUDI-01-00A0.dtbo \
+	BB-BONE-LCD4-01-00A0.dtbo \
+	BB-BONE-LCD4-01-00A1.dtbo \
+	BB-BONE-LCD7-01-00A2.dtbo \
+	BB-BONE-LCD7-01-00A3.dtbo \
+	BB-BONE-LCD7-01-00A4.dtbo \
+	BB-BONE-eMMC1-01-00A0.dtbo \
+	BB-BONE-GPEVT-00A0.dtbo \
+	BB-BONE-RS232-00A0.dtbo \
+	BB-BONE-SERL-01-00A1.dtbo \
+	cape-bone-iio-00A0.dtbo \
+	cape-bone-pinmux-test-00A0.dtbo \
+	cape-bone-exptest-00A0.dtbo \
+	cape-bone-mrf24j40-00A0.dtbo \
+	BB-BONELT-BT-00A0.dtbo \
+	am33xx_pwm-00A0.dtbo \
+	bone_pwm_P8_13-00A0.dtbo \
+	bone_pwm_P8_19-00A0.dtbo \
+	bone_pwm_P8_34-00A0.dtbo \
+	bone_pwm_P8_36-00A0.dtbo \
+	bone_pwm_P8_45-00A0.dtbo \
+	bone_pwm_P8_46-00A0.dtbo \
+	bone_pwm_P9_14-00A0.dtbo \
+	bone_pwm_P9_16-00A0.dtbo \
+	bone_pwm_P9_21-00A0.dtbo \
+	bone_pwm_P9_22-00A0.dtbo \
+	bone_pwm_P9_28-00A0.dtbo \
+	bone_pwm_P9_29-00A0.dtbo \
+	bone_pwm_P9_31-00A0.dtbo \
+	bone_pwm_P9_42-00A0.dtbo \
+	BB-BONE-PWMT-00A0.dtbo \
+	BB-BONE-PRU-01-00A0.dtbo \
+	BB-BONE-PRU-02-00A0.dtbo \
+	BB-BONE-RST-00A0.dtbo \
+	BB-BONE-RST2-00A0.dtbo \
+	BB-BONE-CAM3-01-00A2.dtbo \
+	TT3201-001-01.dtbo \
+	BB-BONE-SERL-03-00A1.dtbo \
+	BB-BONE-PRU-01-00A0.dtbo
+
+# the geiger cape
+fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_GEIGER) += \
+	cape-bone-geiger-00A0.dtbo
+
+# the nixie cape
+fw-shipped-$(CONFIG_CAPE_BEAGLEBONE_NIXIE) += \
+	cape-bone-nixie-00A0.dtbo
+
+# the weather cape
+fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-bone-weather-00A0.dtbo
+
+# the HDMI virtual capes on the beaglebone-black
+fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+	cape-boneblack-hdmi-00A0.dtbo cape-boneblack-hdmin-00A0.dtbo
+
+# the Tester cape (tester-side)
+fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += cape-bone-tester-00A0.dtbo
+
+# the virtual peripheral capes for the UARTs
+# UART3 is not routed to the connectors, no cape for it
+fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+	BB-UART1-00A0.dtbo BB-UART2-00A0.dtbo \
+	BB-UART4-00A0.dtbo BB-UART5-00A0.dtbo
+
+# the virtual peripheral capes for the I2Cs
+# I2C0 & I2C2 are enabled by default, no capes for them
+fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+	BB-I2C1-00A0.dtbo BB-I2C1A1-00A0.dtbo
+
+# the virtual peripheral capes for the SPIs
+fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+	BB-SPI0-00A0.dtbo BB-SPI1-00A0.dtbo BB-SPI1A1-00A0.dtbo
+
+# the virtual peripheral capes for ADC
+fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+	BB-ADC-00A0.dtbo
+
+# the virtual peripheral capes for GPIO
+fw-shipped-$(CONFIG_CAPE_BEAGLEBONE) += \
+	BB-GPIOHELP-00A0.dtbo
+
+# PRU firmware
+#fw-shipped-$(CONFIG_PRU_RPROC) += \
+#	prutest.bin
+
 fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
 
 # Directories which we _might_ need to create, so we have a rule for them.
@@ -147,6 +243,9 @@ quiet_cmd_mkdir = MKDIR   $(patsubst $(objtree)/%,%,$@)
 quiet_cmd_ihex  = IHEX    $@
       cmd_ihex  = $(OBJCOPY) -Iihex -Obinary $< $@
 
+quiet_cmd_dtco	= DTCO $@
+      cmd_dtco	= $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -@ $<
+
 quiet_cmd_ihex2fw  = IHEX2FW $@
       cmd_ihex2fw  = $(objtree)/$(obj)/ihex2fw $< $@
 
@@ -233,6 +332,10 @@ $(obj)/%.fw: $(obj)/%.HEX $(ihex2fw_dep) | $(objtree)/$(obj)/$$(dir %)
 $(obj)/%.fw: $(obj)/%.H16 $(ihex2fw_dep) | $(objtree)/$(obj)/$$(dir %)
 	$(call cmd,h16tofw)
 
+# DTBO is device tree blob object
+$(obj)/%.dtbo: $(obj)/capes/%.dts | $(objtree)/$(obj)/$$(dir %)
+	$(call cmd,dtco)
+
 $(firmware-dirs):
 	$(call cmd,mkdir)
 
diff --git a/firmware/capes/BB-ADC-00A0.dts b/firmware/capes/BB-ADC-00A0.dts
new file mode 100644
index 0000000..88f6fc6
--- /dev/null
+++ b/firmware/capes/BB-ADC-00A0.dts
@@ -0,0 +1,59 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-ADC";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.39",	/* AIN0 */
+		"P9.40",	/* AIN1 */
+		"P9.37",	/* AIN2 */
+		"P9.38",	/* AIN3 */
+		"P9.33",	/* AIN4 */
+		"P9.36",	/* AIN5 */
+		"P9.35",	/* AIN6 */
+		/* the hardware IP uses */
+		"tscadc";
+
+	fragment@0 {
+		target = <&ocp>;
+		__overlay__ {
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			tscadc {
+				compatible = "ti,ti-tscadc";
+				reg = <0x44e0d000 0x1000>;
+
+				interrupt-parent = <&intc>;
+				interrupts = <16>;
+				ti,hwmods = "adc_tsc";
+				status = "okay";
+
+				adc {
+					ti,adc-channels = <0 1 2 3 4 5 6 7>;
+				};
+			};
+
+			test_helper: helper {
+				compatible = "bone-iio-helper";
+				vsense-name  = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
+				vsense-scale = <100     100     100     100     100     100     100     100>;
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-AUDI-01-00A0.dts b/firmware/capes/BB-BONE-AUDI-01-00A0.dts
new file mode 100644
index 0000000..5e145b9
--- /dev/null
+++ b/firmware/capes/BB-BONE-AUDI-01-00A0.dts
@@ -0,0 +1,138 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-AUDI-01";
+	version = "00A0", "A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.14",	/* leds:   gpio1_18 */
+		"P9.16",	/* leds:   gpio1_19 */
+		"P9.31",	/* mcasp0: mcasp0_aclkx */
+		"P9.29",	/* mcasp0: mcasp0_fsx */
+		"P9.28",	/* mcasp0: mcasp0_axr2 */
+		"P9.25",	/* mcasp0: mcasp0_ahclkx */
+		/* the hardware ip uses */
+		"gpio1_18", "gpio1_19",
+		"mcasp0";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_audio_cape_led_pins: pinmux_bone_audio_cape_led_pins {
+				pinctrl-single,pins = <
+					0x48 0x07	/* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
+					0x4c 0x07	/* gpmc_a3.gpio1_19, OUTPUT | MODE7 */
+				>;
+			};
+
+			bone_audio_cape_audio_pins: pinmux_bone_audio_cape_audio_pins {
+				pinctrl-single,pins = <
+					0x190 0x20	/* mcasp0_aclkx.mcasp0_aclkx, INPUT | MODE0 */
+					0x194 0x20	/* mcasp0_fsx.mcasp0_fsx, INPUT | MODE0 */
+					0x19c 0x22	/* mcasp0_ahclkr.mcasp0_axr2, INPUT | MODE2 */
+					0x1ac 0x22	/* mcasp0_ahclkx.mcasp0_axr3, INPUT | MODE2 */
+
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			gpio-leds-cape-audio {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_audio_cape_led_pins>;
+
+				audio-led0 {
+					label = "audio:green:usr0";
+					gpios = <&gpio2 18 0>;
+					linux,default-trigger = "heartbeat";
+					default-state = "off";
+				};
+
+				audio-led1 {
+					label = "audio:green:usr1";
+					gpios = <&gpio2 19 0>;
+					linux,default-trigger = "mmc0";
+					default-state = "off";
+				};
+			};
+		};
+	};
+
+	fragment@2 {
+		target = <&i2c2>;
+		__overlay__ {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			tlv320aic3x: tlv320aic3x@1b {
+				compatible = "ti,tlv320aic3x";
+				reg = <0x1b>;
+				status = "okay";
+			};
+		};
+	};
+
+	fragment@3 {
+		target = <&mcasp0>;
+		__overlay__ {
+			pinctrl-names = "default";
+			pinctrl-0 = <&bone_audio_cape_audio_pins>;
+
+			status = "okay";
+
+			op-mode = <0>;          /* MCASP_IIS_MODE */
+			tdm-slots = <2>;
+			num-serializer = <16>;
+			serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+				0 0 2 1
+				0 0 0 0
+				0 0 0 0
+				0 0 0 0
+			>;
+			tx-num-evt = <1>;
+			rx-num-evt = <1>;
+		};
+	};
+
+	fragment@4 {
+		target = <&ocp>;
+		__overlay__ {
+			sound {
+				compatible = "ti,da830-evm-audio";
+				ti,model = "DA830 EVM";
+				ti,audio-codec = <&tlv320aic3x>;
+				ti,mcasp-controller = <&mcasp0>;
+				ti,codec-clock-rate = <12000000>;
+				ti,audio-routing =
+					"Headphone Jack",       "HPLOUT",
+					"Headphone Jack",       "HPROUT",
+					"LINE1L",               "Line In",
+					"LINE1R",               "Line In";
+			};
+		};
+
+	};
+};
diff --git a/firmware/capes/BB-BONE-CAM3-01-00A2.dts b/firmware/capes/BB-BONE-CAM3-01-00A2.dts
new file mode 100644
index 0000000..2470a76
--- /dev/null
+++ b/firmware/capes/BB-BONE-CAM3-01-00A2.dts
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2013 Circuit Co.
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-CAM3-01";
+	version = "00A2", "A2";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.25",	/* gpmc: gpmc_ad0 */
+		"P8.24",	/* gpmc: gpmc_ad1 */
+		"P8.5",		/* gpmc: gpmc_ad2 */
+		"P8.6",		/* gpmc: gpmc_ad3 */
+		"P8.23",	/* gpmc: gpmc_ad4 */
+		"P8.22",	/* gpmc: gpmc_ad5 */
+		"P8.3",		/* gpmc: gpmc_ad6 */
+		"P8.4",		/* gpmc: gpmc_ad7 */
+		"P8.19",	/* gpmc: gpmc_ad8 */
+		"P8.13",	/* gpmc: gpmc_ad9 */
+		"P8.14",	/* gpmc: gpmc_ad10 */
+		"P8.17",	/* gpmc: gpmc_ad11 */
+		"P8.12",	/* gpmc: gpmc_ad12 */
+		"P8.11",	/* gpmc: gpmc_ad13 */
+		"P8.16",	/* gpmc: gpmc_ad14 */
+		"P8.15",	/* gpmc: gpmc_ad15 */
+		"P9.13",	/* gpmc: gpmc_wpn */
+		"P8.21",	/* gpmc: gpmc_csn1 */
+		"P8.18",	/* gpmc: gpmc_clk */
+		"P8.7",		/* gpmc: gpmc_advn_ale */
+		"P8.8",		/* gpmc: gpmc_oen_ren */
+		"P8.10",	/* gpmc: gpmc_wen */
+		"P8.9",		/* gpmc: gpmc_ben0_cle */
+		"P9.41",	/* cssp: clkout2 */
+		"P9.42",	/* cssp: xdma_event_intr2 */
+		"P9.18",	/* cssp: gpio0_4 */
+		"P9.17",	/* cssp: gpio0_5 */
+		"P9.11",	/* cssp: gpio0_30 */
+
+		/* the hardware IP uses */
+		"gpio0_4",
+		"gpio0_5",
+		"gpio0_30",
+		"gpmc",
+		"clkout2",
+		/* the reset pin */
+		"eMMC_RSTn";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			gpmc_pins: pinmux_gpmc_pins {
+				pinctrl-single,pins = <
+					0x000 0x30	/* gpmc_ad0.gpmc_ad0 MODE0 | INPUT | PULLUP */
+					0x004 0x30	/* gpmc_ad1.gpmc_ad1 MODE0 | INPUT | PULLUP */
+					0x008 0x30	/* gpmc_ad2.gpmc_ad2 MODE0 | INPUT | PULLUP */
+					0x00C 0x30	/* gpmc_ad3.gpmc_ad3 MODE0 | INPUT | PULLUP */
+					0x010 0x30	/* gpmc_ad4.gpmc_ad4 MODE0 | INPUT | PULLUP */
+					0x014 0x30	/* gpmc_ad5.gpmc_ad5 MODE0 | INPUT | PULLUP */
+					0x018 0x30	/* gpmc_ad6.gpmc_ad6 MODE0 | INPUT | PULLUP */
+					0x01C 0x30	/* gpmc_ad7.gpmc_ad7 MODE0 | INPUT | PULLUP */
+					0x020 0x30	/* gpmc_ad8.gpmc_ad8 MODE0 | INPUT | PULLUP */
+					0x024 0x30	/* gpmc_ad9.gpmc_ad9 MODE0 | INPUT | PULLUP */
+					0x028 0x30	/* gpmc_ad10.gpmc_ad10 MODE0 | INPUT | PULLUP */
+					0x02C 0x30	/* gpmc_ad11.gpmc_ad11 MODE0 | INPUT | PULLUP */
+					0x030 0x30	/* gpmc_ad12.gpmc_ad12 MODE0 | INPUT | PULLUP */
+					0x034 0x30	/* gpmc_ad13.gpmc_ad13 MODE0 | INPUT | PULLUP */
+					0x038 0x30	/* gpmc_ad14.gpmc_ad14 MODE0 | INPUT | PULLUP */
+					0x03C 0x30	/* gpmc_ad15.gpmc_ad15 MODE0 | INPUT | PULLUP */
+					0x074 0x30	/* gpmc_wpn.gpmc_wpn MODE0 | INPUT | PULLUP */ /* WAS MODE 7 */
+					0x080 0x08	/* gpmc_cscn1.gpmc_cscn1 MODE0 | OUTPUT */
+					0x08C 0x28	/* gpmc_clk.gpmc_clk MODE0 | INPUT */
+					0x090 0x08	/* gpmc_advn_ale.gpmc_advn_ale MODE0 | OUTPUT */
+					0x094 0x08	/* gpmc_oen_ren.gpmc_oen_ren MODE0 | OUTPUT */
+					0x098 0x08	/* gpmc_wen.gpmc_wen MODE0 | OUTPUT */
+					0x09C 0x08	/* gpmc_ben0_cle.gpmc_ben0_cle MODE0 | OUTPUT */
+				>;
+			};
+			cssp_camera_pins: pinmux_cssp_camera_pins {
+				pinctrl-single,pins = <
+					/* clkout2 */
+					0x1B4 0x03	/* xdma_event_intr1.clkout2 MODE3 | OUTPUT clkout2 */
+
+					/* dmar */
+					0x164 0x2e	/* ecap0_in_pwm0_out.xdma_event_intr2 MODE6 | INPUT */
+
+					/* cssp camera */
+					0x158 0x07	/* spi0_d1.gpio0_4 MODE7 | OUTPUT, QL CSSP and Camera Sensor Reset */
+					0x15C 0x17	/* spi0_cs0.gpio0_5 MODE7 | OUTPUT | PULLUP, 1V8 and 2V8 Power Enable */
+					0x070 0x2f	/* gpmc_wait0.gpio0_30 MODE0 | INPUT | PULLUPDIS, Sensor orientation detect: low -> frontfacing, high -> backfacing */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&gpmc>;
+		depth = <1>;	/* only create devices on depth 1 */
+
+		/* stupid warnings */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		__overlay__ {
+
+			status = "okay";
+
+			#address-cells = <2>;
+			#size-cells = <1>;
+
+			pinctrl-names = "default";
+			pinctrl-0 = <&gpmc_pins>;
+
+			/* chip select ranges */
+			ranges = <0 0 0x08000000 0x10000000>,	/* bootloader has this enabled */
+				 <1 0 0x18000000 0x08000000>,
+				 <2 0 0x20000000 0x08000000>,
+				 <3 0 0x28000000 0x08000000>,
+				 <4 0 0x30000000 0x08000000>,
+				 <5 0 0x38000000 0x04000000>,
+				 <6 0 0x3c000000 0x04000000>;
+
+			/*
+			 * This is complete and utter cr*p
+			 * It doesn't belong here, but we don't
+			 * have a memory controller abstraction.
+			 * So we muddle along...
+			 */
+			camera {
+				compatible = "cssp-camera";
+				status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <&cssp_camera_pins>;
+
+				reg = <1 0 0x01000000>;		/* CS1 */
+
+				bank-width = <2>;		/* GPMC_CONFIG1_DEVICESIZE(1) */
+
+				gpmc,burst-read;		/* GPMC_CONFIG1_READMULTIPLE_SUPP */
+				gpmc,sync-read;			/* GPMC_CONFIG1_READTYPE_SYNC */
+				gpmc,sync-write;		/* GPMC_CONFIG1_WRITETYPE_SYNC */
+				gpmc,clk-activation-ns = <20>;	/* GPMC_CONFIG1_CLKACTIVATIONTIME(2) */
+				gpmc,burst-length = <16>;	/* GPMC_CONFIG1_PAGE_LEN(2) */
+				gpmc,mux-add-data = <2>;	/* GPMC_CONFIG1_MUXTYPE(2) */
+
+				gpmc,sync-clk-ps = <20000>;	/* CONFIG2 */
+
+				gpmc,cs-on-ns = <1>;
+				gpmc,cs-rd-off-ns = <160>;
+				gpmc,cs-wr-off-ns = <310>;
+
+				gpmc,adv-on-ns = <0>;		/* CONFIG3 */
+				gpmc,adv-rd-off-ns = <40>;
+				gpmc,adv-wr-off-ns = <40>;
+
+				gpmc,we-on-ns = <60>;		/* CONFIG4 */
+				gpmc,we-off-ns = <310>;
+				gpmc,oe-on-ns = <60>;
+				gpmc,oe-off-ns = <160>;
+
+				gpmc,page-burst-access-ns = <20>;	/* CONFIG 5 */
+				gpmc,access-ns = <140>;
+				gpmc,rd-cycle-ns = <160>;
+				gpmc,wr-cycle-ns = <310>;
+
+				gpmc,wr-access-ns = <100>;		/* CONFIG 6 */
+				gpmc,wr-data-mux-bus-ns = <60>;
+
+				gpmc,bus-turnaround-ns = <40>;		/* CONFIG6:3:0 = 4 */
+				gpmc,cycle2cycle-samecsen;		/* CONFIG6:7 = 1 */
+				gpmc,cycle2cycle-delay-ns = <40>;	/* CONFIG6:11:8 = 4 */
+
+				/* not using dma engine yet, but we can get the channel number here */
+				dmas = <&edma 20>;
+				dma-names = "cssp";
+
+				/* clocks */
+				cssp,camera-clk-name = "adjustable_clkout2_ck";
+				cssp,camera-clk-rate = <32000000>;
+
+				/* reset */
+				reset-gpio = <&gpio1 4 0>;
+
+				/* orientation; -> MT9T112_FLAG_VFLIP */
+				orientation-gpio = <&gpio1 30 0>;
+
+				/* reset controller (for the black) */
+				reset = <&rstctl 0 0>;
+				reset-names = "eMMC_RSTn-CAM3";
+
+				/* camera sensor */
+				cssp,sensor {
+					i2c-adapter = <&i2c2>;
+
+					/* need it to stop the whinning */
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* fake i2c device node */
+					m59t112 {
+						compatible = "aptina,mt9t112";
+						reg = <0x3c>;
+
+						/* m, n, p1-7 */
+						flags = <0>;
+						pll-divider = <24 1 0 7 0 10 14 7 0>;
+					};
+				};
+
+			};
+
+		};
+	};
+
+};
diff --git a/firmware/capes/BB-BONE-GPEVT-00A0.dts b/firmware/capes/BB-BONE-GPEVT-00A0.dts
new file mode 100644
index 0000000..e773dee
--- /dev/null
+++ b/firmware/capes/BB-BONE-GPEVT-00A0.dts
@@ -0,0 +1,48 @@
+/*
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-GPEVT";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.7",
+		/* the hardware IP uses */
+		"gpio2_2";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			gpevt_pins_s0: pinmux_gpevt_pins_s0 {
+				pinctrl-single,pins = <
+					0x090 0x37	/* gpmc_advn_ale.gpio2_2, INPUT_PULLUP | MODE7 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			gpevt {
+				compatible = "gpevt";
+				pinctrl-names = "default";
+				pinctrl-0 = <&gpevt_pins_s0>;
+
+				dmas = <&edma 12>;
+				dma-names = "gpioevt";
+				gpio-evt = <&gpio3 2 0>;
+			};
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-LCD4-01-00A0.dts b/firmware/capes/BB-BONE-LCD4-01-00A0.dts
new file mode 100644
index 0000000..f355b06
--- /dev/null
+++ b/firmware/capes/BB-BONE-LCD4-01-00A0.dts
@@ -0,0 +1,192 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-LCD4-01";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.45",	/* lcd: lcd_data0 */
+		"P8.46",	/* lcd: lcd_data1 */
+		"P8.43",	/* lcd: lcd_data2 */
+		"P8.44",	/* lcd: lcd_data3 */
+		"P8.41",	/* lcd: lcd_data4 */
+		"P8.42",	/* lcd: lcd_data5 */
+		"P8.39",	/* lcd: lcd_data6 */
+		"P8.40",	/* lcd: lcd_data7 */
+		"P8.37",	/* lcd: lcd_data8 */
+		"P8.38",	/* lcd: lcd_data9 */
+		"P8.36",	/* lcd: lcd_data10 */
+		"P8.34",	/* lcd: lcd_data11 */
+		"P8.35",	/* lcd: lcd_data12 */
+		"P8.33",	/* lcd: lcd_data13 */
+		"P8.31",	/* lcd: lcd_data14 */
+		"P8.32",	/* lcd: lcd_data15 */
+		"P8.27",	/* lcd: lcd_vsync */
+		"P8.29",	/* lcd: lcd_hsync */
+		"P8.28",	/* lcd: lcd_pclk */
+		"P8.30",	/* lcd: lcd_ac_bias_en */
+		"P9.16",	/* tsc: gpio1_19 */
+		"P9.14",	/* led: gpio1_18 */
+		/* the hardware IP uses */
+		"gpio1_19",
+		"gpio1_18",
+		"lcd",
+		"tps-bl";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_lcd4_cape_led_00A0_pins: pinmux_bone_lcd4_cape_led_00A0_pins {
+				pinctrl-single,pins = <
+					0x48 0x07	/* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
+				>;
+			};
+
+			bone_lcd4_cape_lcd_pins: pinmux_bone_lcd4_cape_lcd_pins {
+				pinctrl-single,pins = <
+					0xa0 0x08	/* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa4 0x08	/* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa8 0x08	/* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xac 0x08	/* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb0 0x08	/* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb4 0x08	/* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb8 0x08	/* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xbc 0x08	/* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc0 0x08	/* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc4 0x08	/* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc8 0x08	/* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xcc 0x08	/* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd0 0x08	/* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd4 0x08	/* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd8 0x08	/* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xdc 0x08	/* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xe0 0x00	/* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe4 0x00	/* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe8 0x00	/* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xec 0x00	/* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+				 	0x4c 0x27       /* TSC_INT gpmc_a3.gpio1_19, INPUT | MODE7 */
+				>;
+			};
+
+		};
+	};
+
+	fragment@1 {
+		target = <&tps>;
+		__overlay__ {
+			backlight {
+				compatible = "not-tps65217-backlight";
+				isel = <1>;
+				fdim = <200>;
+				brightness = <100>;
+				tps = <&tps>;
+			};
+		};
+	};
+
+	fragment@2 {
+		target = <&ocp>;
+
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			tscadc {
+				compatible = "ti,ti-tscadc";
+				reg = <0x44e0d000 0x1000>;
+
+				interrupt-parent = <&intc>;
+				interrupts = <16>;
+				ti,hwmods = "adc_tsc";
+				status = "okay";
+
+				tsc {
+					ti,wires = <4>;
+					ti,x-plate-resistance = <200>;
+					ti,coordinate-readouts = <5>;
+					ti,wire-config = <0x00 0x11 0x22 0x33>;
+				};
+
+				adc {
+					ti,adc-channels = <4 5 6 7>;
+				};
+			};
+
+			gpio-leds-cape-lcd4 {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+
+				pinctrl-0 = <&bone_lcd4_cape_led_00A0_pins>;
+
+				lcd4-led0 {
+					label = "lcd4:green:usr0";
+					gpios = <&gpio2 18 0>;
+					linux,default-trigger = "heartbeat";
+					default-state = "off";
+				};
+			};
+
+			/* Settings for NHD-4.3-ATXI#-T-1 / LCD4 cape: */
+			panel {
+				compatible = "tilcdc,panel";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd4_cape_lcd_pins>;
+				panel-info {
+					ac-bias           = <255>;
+					ac-bias-intrpt    = <0>;
+					dma-burst-sz      = <16>;
+					bpp               = <24>;
+					fdd               = <0x80>;
+					tft-alt-mode      = <0>;
+					stn-565-mode      = <0>;
+					mono-8bit-mode    = <0>;
+					sync-edge         = <0>;
+					sync-ctrl         = <1>;
+					raster-order      = <0>;
+					fifo-th           = <0>;
+				};
+				display-timings {
+					native-mode = <&timing0>;
+					timing0: 480x272 {
+						hactive         = <480>;
+						vactive         = <272>;
+						hback-porch     = <44>;
+						hfront-porch    = <9>;
+						hsync-len       = <5>;
+						vback-porch     = <13>;
+						vfront-porch    = <4>;
+						vsync-len       = <10>;
+						clock-frequency = <9000000>;
+						hsync-active    = <0>;
+						vsync-active    = <0>;
+					};
+				};
+			};
+
+			fb {
+				compatible = "ti,am33xx-tilcdc";
+				reg = <0x4830e000 0x1000>;
+				interrupt-parent = <&intc>;
+				interrupts = <36>;
+				ti,hwmods = "lcdc";
+			};
+
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-LCD4-01-00A1.dts b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
new file mode 100644
index 0000000..19f52fc
--- /dev/null
+++ b/firmware/capes/BB-BONE-LCD4-01-00A1.dts
@@ -0,0 +1,279 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-LCD4-01";
+	version = "00A1";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.45",	/* lcd: lcd_data0 */
+		"P8.46",	/* lcd: lcd_data1 */
+		"P8.43",	/* lcd: lcd_data2 */
+		"P8.44",	/* lcd: lcd_data3 */
+		"P8.41",	/* lcd: lcd_data4 */
+		"P8.42",	/* lcd: lcd_data5 */
+		"P8.39",	/* lcd: lcd_data6 */
+		"P8.40",	/* lcd: lcd_data7 */
+		"P8.37",	/* lcd: lcd_data8 */
+		"P8.38",	/* lcd: lcd_data9 */
+		"P8.36",	/* lcd: lcd_data10 */
+		"P8.34",	/* lcd: lcd_data11 */
+		"P8.35",	/* lcd: lcd_data12 */
+		"P8.33",	/* lcd: lcd_data13 */
+		"P8.31",	/* lcd: lcd_data14 */
+		"P8.32",	/* lcd: lcd_data15 */
+		"P8.27",	/* lcd: lcd_vsync */
+		"P8.29",	/* lcd: lcd_hsync */
+		"P8.28",	/* lcd: lcd_pclk */
+		"P8.30",	/* lcd: lcd_ac_bias_en */
+		"P9.27",	/* lcd: gpio3_19 */
+		"P9.12",	/* led: gpio1_28 */
+		"P9.14",	/* pwm: ehrpwm1a */
+		"P9.15",	/* keys: gpio1_16 */
+		"P9.23",	/* keys: gpio1_17 */
+		"P9.16",	/* keys: gpio1_19 */
+		"P9.21",	/* keys: gpio0_3 */
+		/* the hardware IP uses */
+		"gpio3_19",
+		"gpio1_28",
+		"gpio1_16",
+		"gpio1_17",
+		"gpio1_19",
+		"gpio0_3",
+		"lcd",
+		"ehrpwm1a";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_lcd4_cape_led_00A1_pins: pinmux_bone_lcd4_cape_led_00A1_pins {
+				pinctrl-single,pins = <
+					0x078 0x2f      /* gpmc_be1n.gpio1_28, INPUT | PULLDIS | MODE7 */
+				>;
+			};
+
+			pwm_bl_pins: pinmux_pwm_bl_pins {
+				pinctrl-single,pins = <
+					0x48 0x06       /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+
+			bone_lcd4_cape_lcd_pins: pinmux_bone_lcd4_cape_lcd_pins {
+				pinctrl-single,pins = <
+					0xa0 0x08	/* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa4 0x08	/* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa8 0x08	/* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xac 0x08	/* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb0 0x08	/* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb4 0x08	/* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb8 0x08	/* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xbc 0x08	/* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc0 0x08	/* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc4 0x08	/* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc8 0x08	/* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xcc 0x08	/* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd0 0x08	/* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd4 0x08	/* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd8 0x08	/* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xdc 0x08	/* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xe0 0x00	/* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe4 0x00	/* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe8 0x00	/* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xec 0x00	/* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0x1a4 0x17	/* mcasp0_fsr.gpio3_19, OUTPUT | MODE7  LCD DISEN */
+				>;
+			};
+
+			bone_lcd4_cape_keys_00A2_pins: pinmux_bone_lcd4_cape_keys_00A2_pins {
+				pinctrl-single,pins = <
+					0x040 0x2f	/* gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
+					0x044 0x2f	/* gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
+					0x04c 0x2f 	/* gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
+					0x154 0x2f	/* P9_21 spi0_d0.gpio0_3 INPUT | PULLDIS | MODE7 */
+				>;
+			};
+
+		};
+	};
+
+	fragment@1 {
+		target = <&epwmss1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@2 {
+		target = <&ehrpwm1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@3 {
+		target = <&ocp>;
+
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			backlight {
+				compatible      = "pwm-backlight";
+ 				pinctrl-names   = "default";
+				pinctrl-0       = <&pwm_bl_pins>;
+
+				pwms = <&ehrpwm1 0 500000 0>;
+				pwm-names = "LCD4";
+				brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+				default-brightness-level = <101>; /* index to the array above */
+				status = "okay";
+ 			};
+
+			tscadc {
+				compatible = "ti,ti-tscadc";
+				reg = <0x44e0d000 0x1000>;
+
+				interrupt-parent = <&intc>;
+				interrupts = <16>;
+				ti,hwmods = "adc_tsc";
+				status = "okay";
+
+				tsc {
+					ti,wires = <4>;
+					ti,x-plate-resistance = <200>;
+					ti,coordinate-readouts = <5>;
+					ti,wire-config = <0x00 0x11 0x22 0x33>;
+				};
+
+				adc {
+					ti,adc-channels = <4 5 6 7>;
+				};
+			};
+
+			gpio-leds-cape-lcd4 {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+
+				pinctrl-0 = <&bone_lcd4_cape_led_00A1_pins>;
+
+				lcd4-led0 {
+					label = "lcd4:green:usr0";
+					gpios = <&gpio2 28 0>;
+					linux,default-trigger = "heartbeat";
+					default-state = "off";
+				};
+
+			};
+
+			gpio_keys {
+				compatible = "gpio-keys";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd4_cape_keys_00A2_pins>;
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				button@1 {
+					debounce_interval = <50>;
+					linux,code = <105>;
+					label = "left";
+					gpios = <&gpio2 16 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@2 {
+					debounce_interval = <50>;
+					linux,code = <106>;
+					label = "right";
+					gpios = <&gpio2 17 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@3 {
+					debounce_interval = <50>;
+					linux,code = <103>;
+					label = "up";
+					gpios = <&gpio2 19 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@4 {
+					debounce_interval = <50>;
+					linux,code = <108>;
+					label = "down";
+					gpios = <&gpio4 16 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@5 {
+					debounce_interval = <50>;
+					linux,code = <28>;
+					label = "enter";
+					gpios = <&gpio1 15 0x1>;
+					gpio-key,wakeup;
+				};
+			};
+
+			/* Settings for NHD-4.3-ATXI#-T-1 / LCD4 cape: */
+			panel {
+				compatible = "tilcdc,panel";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd4_cape_lcd_pins>;
+				panel-info {
+					ac-bias           = <255>;
+					ac-bias-intrpt    = <0>;
+					dma-burst-sz      = <16>;
+					bpp               = <24>;
+					fdd               = <0x80>;
+					tft-alt-mode      = <0>;
+					stn-565-mode      = <0>;
+					mono-8bit-mode    = <0>;
+					sync-edge         = <0>;
+					sync-ctrl         = <1>;
+					raster-order      = <0>;
+					fifo-th           = <0>;
+				};
+				display-timings {
+					native-mode = <&timing0>;
+					timing0: 480x272 {
+						hactive         = <480>;
+						vactive         = <272>;
+						hback-porch     = <44>;
+						hfront-porch    = <9>;
+						hsync-len       = <5>;
+						vback-porch     = <13>;
+						vfront-porch    = <4>;
+						vsync-len       = <10>;
+						clock-frequency = <9000000>;
+						hsync-active    = <0>;
+						vsync-active    = <0>;
+					};
+				};
+			};
+
+			fb {
+				compatible = "ti,am33xx-tilcdc";
+				reg = <0x4830e000 0x1000>;
+				interrupt-parent = <&intc>;
+				interrupts = <36>;
+				ti,hwmods = "lcdc";
+			};
+
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-LCD7-01-00A2.dts b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
new file mode 100644
index 0000000..03645ad
--- /dev/null
+++ b/firmware/capes/BB-BONE-LCD7-01-00A2.dts
@@ -0,0 +1,282 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-LCD7-01";
+	version = "00A2";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.45",	/* lcd: lcd_data0 */
+		"P8.46",	/* lcd: lcd_data1 */
+		"P8.43",	/* lcd: lcd_data2 */
+		"P8.44",	/* lcd: lcd_data3 */
+		"P8.41",	/* lcd: lcd_data4 */
+		"P8.42",	/* lcd: lcd_data5 */
+		"P8.39",	/* lcd: lcd_data6 */
+		"P8.40",	/* lcd: lcd_data7 */
+		"P8.37",	/* lcd: lcd_data8 */
+		"P8.38",	/* lcd: lcd_data9 */
+		"P8.36",	/* lcd: lcd_data10 */
+		"P8.34",	/* lcd: lcd_data11 */
+		"P8.35",	/* lcd: lcd_data12 */
+		"P8.33",	/* lcd: lcd_data13 */
+		"P8.31",	/* lcd: lcd_data14 */
+		"P8.32",	/* lcd: lcd_data15 */
+		"P8.27",	/* lcd: lcd_vsync */
+		"P8.29",	/* lcd: lcd_hsync */
+		"P8.28",	/* lcd: lcd_pclk */
+		"P8.30",	/* lcd: lcd_ac_bias_en */
+		"P8.20",	/* lcd: gpio1_31 */
+		"P9.12",	/* led: gpio1_28 */
+		"P9.14",	/* pwm: ehrpwm1a */
+		"P9.15",	/* keys: gpio1_16 */
+		"P9.23",	/* keys: gpio1_17 */
+		"P9.16",	/* keys: gpio1_19 */
+		"P9.27",	/* keys: gpio3_19 */
+		/* the hardware IP uses */
+		"gpio1_31",
+		"gpio1_28",
+		"gpio1_16",
+		"gpio1_17",
+		"gpio1_19",
+		"gpio3_19",
+		"lcd",
+		"ehrpwm1a";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_lcd7_cape_led_00A2_pins: pinmux_bone_lcd7_cape_led_00A2_pins {
+				pinctrl-single,pins = <
+					0x078 0x2f	/* gpmc_be1n.gpio1_28, INPUT | PULLDIS | MODE7 */
+				>;
+			};
+
+			pwm_bl_pins: pinmux_pwm_bl_pins {
+				pinctrl-single,pins = <
+					0x48 0x06       /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+
+			bone_lcd7_cape_lcd_pins: pinmux_bone_lcd7_cape_lcd_pins {
+				pinctrl-single,pins = <
+					0x84 0x07	/* gpmc_csn2.gpio1_31, OUTPUT | MODE7 - AVDD_EN */
+					0xa0 0x08	/* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa4 0x08	/* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa8 0x08	/* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xac 0x08	/* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb0 0x08	/* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb4 0x08	/* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb8 0x08	/* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xbc 0x08	/* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc0 0x08	/* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc4 0x08	/* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc8 0x08	/* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xcc 0x08	/* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd0 0x08	/* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd4 0x08	/* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd8 0x08	/* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xdc 0x08	/* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xe0 0x00	/* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe4 0x00	/* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe8 0x00	/* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xec 0x00	/* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+
+			bone_lcd7_cape_keys_00A2_pins: pinmux_bone_lcd7_cape_keys_00A2_pins {
+				pinctrl-single,pins = <
+					0x040 0x2f	/* KEY_LEFT gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
+					0x044 0x2f	/* KEY_RIGHT gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
+					0x04c 0x2f 	/* KEY_UP gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
+					0x198 0x2f	/* KEY_DOWN mcasp0_axr0.gpio3_16, INPUT | PULLDIS | MODE7 */
+					0x1a4 0x2f	/* KEY_ENTER mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
+				>;
+			};
+
+		};
+	};
+
+	fragment@1 {
+		target = <&epwmss1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@2 {
+		target = <&ehrpwm1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@3 {
+		target = <&ocp>;
+
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			backlight {
+				compatible      = "pwm-backlight";
+ 				pinctrl-names   = "default";
+				pinctrl-0       = <&pwm_bl_pins>;
+				status = "okay";
+
+				pwms = <&ehrpwm1 0 500000 0>;
+				pwm-names = "LCD7";
+				brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+				default-brightness-level = <101>; /* index to the array above */
+ 			};
+
+			tscadc {
+				compatible = "ti,ti-tscadc";
+				reg = <0x44e0d000 0x1000>;
+
+				interrupt-parent = <&intc>;
+				interrupts = <16>;
+				ti,hwmods = "adc_tsc";
+				status = "okay";
+
+				tsc {
+					ti,wires = <4>;
+					ti,x-plate-resistance = <200>;
+					ti,coordinate-readouts = <5>;
+					ti,wire-config = <0x00 0x11 0x22 0x33>;
+				};
+
+				adc {
+					ti,adc-channels = <4 5 6 7>;
+				};
+			};
+
+			gpio-leds-cape-lcd7 {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+
+				pinctrl-0 = <&bone_lcd7_cape_led_00A2_pins>;
+
+				lcd7-led0 {
+					label = "lcd7:green:usr0";
+					gpios = <&gpio2 28 0>;
+					linux,default-trigger = "heartbeat";
+					default-state = "off";
+				};
+
+			};
+
+			gpio_keys {
+				compatible = "gpio-keys";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd7_cape_keys_00A2_pins>;
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				button@1 {
+					debounce_interval = <50>;
+					linux,code = <105>;
+					label = "left";
+					gpios = <&gpio2 16 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@2 {
+					debounce_interval = <50>;
+					linux,code = <106>;
+					label = "right";
+					gpios = <&gpio2 17 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@3 {
+					debounce_interval = <50>;
+					linux,code = <103>;
+					label = "up";
+					gpios = <&gpio2 19 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@4 {
+					debounce_interval = <50>;
+					linux,code = <108>;
+					label = "down";
+					gpios = <&gpio4 16 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@5 {
+					debounce_interval = <50>;
+					linux,code = <28>;
+					label = "enter";
+					gpios = <&gpio4 19 0x1>;
+					gpio-key,wakeup;
+				};
+			};
+
+			/* Settings for ThreeFive S9700RTWV35TR / LCD7 cape: */
+			panel {
+				compatible = "tilcdc,panel";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd7_cape_lcd_pins>;
+				panel-info {
+					ac-bias           = <255>;
+					ac-bias-intrpt    = <0>;
+					dma-burst-sz      = <16>;
+					bpp               = <16>;
+					fdd               = <0x80>;
+					tft-alt-mode      = <0>;
+					stn-565-mode      = <0>;
+					mono-8bit-mode    = <0>;
+					sync-edge         = <0>;
+					sync-ctrl         = <1>;
+					raster-order      = <0>;
+					fifo-th           = <0>;
+				};
+				display-timings {
+					native-mode = <&timing0>;
+					timing0: 800x480 {
+						hactive         = <800>;
+						vactive         = <480>;
+						hback-porch     = <40>;
+						hfront-porch    = <40>;
+						hsync-len       = <48>;
+						vback-porch     = <30>;
+						vfront-porch    = <13>;
+						vsync-len       = <3>;
+						clock-frequency = <30000000>;
+						hsync-active    = <0>;
+						vsync-active    = <0>;
+					};
+				};
+			};
+
+			fb {
+				compatible = "ti,am33xx-tilcdc";
+				reg = <0x4830e000 0x1000>;
+				interrupt-parent = <&intc>;
+				interrupts = <36>;
+				ti,hwmods = "lcdc";
+				ti,power-gpio = <&gpio2 31 0x0>;
+				ti,allow-non-reduced-blanking-modes;
+			};
+
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-LCD7-01-00A3.dts b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
new file mode 100644
index 0000000..744fc79
--- /dev/null
+++ b/firmware/capes/BB-BONE-LCD7-01-00A3.dts
@@ -0,0 +1,284 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-LCD7-01";
+	version = "00A3";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.45",	/* lcd: lcd_data0 */
+		"P8.46",	/* lcd: lcd_data1 */
+		"P8.43",	/* lcd: lcd_data2 */
+		"P8.44",	/* lcd: lcd_data3 */
+		"P8.41",	/* lcd: lcd_data4 */
+		"P8.42",	/* lcd: lcd_data5 */
+		"P8.39",	/* lcd: lcd_data6 */
+		"P8.40",	/* lcd: lcd_data7 */
+		"P8.37",	/* lcd: lcd_data8 */
+		"P8.38",	/* lcd: lcd_data9 */
+		"P8.36",	/* lcd: lcd_data10 */
+		"P8.34",	/* lcd: lcd_data11 */
+		"P8.35",	/* lcd: lcd_data12 */
+		"P8.33",	/* lcd: lcd_data13 */
+		"P8.31",	/* lcd: lcd_data14 */
+		"P8.32",	/* lcd: lcd_data15 */
+		"P8.27",	/* lcd: lcd_vsync */
+		"P8.29",	/* lcd: lcd_hsync */
+		"P8.28",	/* lcd: lcd_pclk */
+		"P8.30",	/* lcd: lcd_ac_bias_en */
+		"P9.22",	/* lcd: gpio0_2 */
+		"P9.12",	/* led: gpio1_28 */
+		"P9.14",	/* pwm: ehrpwm1a */
+		"P9.15",	/* keys: gpio1_16 */
+		"P9.23",	/* keys: gpio1_17 */
+		"P9.16",	/* keys: gpio1_19 */
+		"P9.30",	/* keys: gpio3_16 */
+		"P9.21",	/* keys: gpio0_3 */
+		/* the hardware IP uses */
+		"gpio0_2",
+		"gpio1_28",
+		"gpio1_16",
+		"gpio1_17",
+		"gpio1_19",
+		"gpio3_16",
+		"gpio0_3",
+		"lcd",
+		"ehrpwm1a";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_lcd7_cape_led_00A3_pins: pinmux_bone_lcd7_cape_led_00A3_pins {
+				pinctrl-single,pins = <
+					0x078 0x2f	/* gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
+				>;
+			};
+
+			pwm_bl_pins: pinmux_pwm_bl_pins {
+				pinctrl-single,pins = <
+					0x48 0x06       /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+
+			bone_lcd7_cape_lcd_pins: pinmux_bone_lcd7_cape_lcd_pins {
+				pinctrl-single,pins = <
+					0x150 0x07	/* spi0_sclk.gpio0_2, OUTPUT | MODE7 - AVDD_EN */
+					0xa0 0x08	/* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa3 0x08	/* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa8 0x08	/* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xac 0x08	/* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb0 0x08	/* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb4 0x08	/* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb8 0x08	/* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xbc 0x08	/* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc0 0x08	/* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc4 0x08	/* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc8 0x08	/* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xcc 0x08	/* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd0 0x08	/* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd4 0x08	/* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd8 0x08	/* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xdc 0x08	/* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xe0 0x00	/* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe4 0x00	/* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe8 0x00	/* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xec 0x00	/* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+
+			bone_lcd7_cape_keys_00A3_pins: pinmux_bone_lcd7_cape_keys_00A3_pins {
+				pinctrl-single,pins = <
+					0x040 0x2f	/* KEY_LEFT gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
+					0x044 0x2f	/* KEY_RIGHT gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
+					0x04c 0x2f 	/* KEY_UP gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
+					0x198 0x2f	/* KEY_DOWN mcasp0_axr0.gpio3_16, INPUT | PULLDIS | MODE7 */
+					0x154 0x2f	/* KEY_ENTER spi0_d0.gpio0_3, INPUT | PULLDIS | MODE7 */
+				>;
+			};
+
+		};
+	};
+
+	fragment@1 {
+		target = <&epwmss1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@2 {
+		target = <&ehrpwm1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@3 {
+		target = <&ocp>;
+
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			backlight {
+				compatible      = "pwm-backlight";
+ 				pinctrl-names   = "default";
+				pinctrl-0       = <&pwm_bl_pins>;
+				status = "okay";
+
+				pwms = <&ehrpwm1 0 500000 0>;
+				pwm-names = "LCD7";
+				brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+				default-brightness-level = <101>; /* index to the array above */
+ 			};
+
+			tscadc {
+				compatible = "ti,ti-tscadc";
+				reg = <0x44e0d000 0x1000>;
+
+				interrupt-parent = <&intc>;
+				interrupts = <16>;
+				ti,hwmods = "adc_tsc";
+				status = "okay";
+
+				tsc {
+					ti,wires = <4>;
+					ti,x-plate-resistance = <200>;
+					ti,coordinate-readouts = <5>;
+					ti,wire-config = <0x00 0x11 0x22 0x33>;
+				};
+
+				adc {
+					ti,adc-channels = <4 5 6 7>;
+				};
+			};
+
+			gpio-leds-cape-lcd7 {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+
+				pinctrl-0 = <&bone_lcd7_cape_led_00A3_pins>;
+
+				lcd7-led0 {
+					label = "lcd7:green:usr0";
+					gpios = <&gpio2 28 0>;
+					linux,default-trigger = "heartbeat";
+					default-state = "off";
+				};
+
+			};
+
+			gpio_keys {
+				compatible = "gpio-keys";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd7_cape_keys_00A3_pins>;
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				button@1 {
+					debounce_interval = <50>;
+					linux,code = <105>;
+					label = "left";
+					gpios = <&gpio2 16 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@2 {
+					debounce_interval = <50>;
+					linux,code = <106>;
+					label = "right";
+					gpios = <&gpio2 17 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@3 {
+					debounce_interval = <50>;
+					linux,code = <103>;
+					label = "up";
+					gpios = <&gpio2 19 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@4 {
+					debounce_interval = <50>;
+					linux,code = <108>;
+					label = "down";
+					gpios = <&gpio4 16 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@5 {
+					debounce_interval = <50>;
+					linux,code = <28>;
+					label = "enter";
+					gpios = <&gpio1 3 0x1>;
+					gpio-key,wakeup;
+				};
+			};
+
+			/* Settings for ThreeFive S9700RTWV35TR / LCD7 cape: */
+			panel {
+				compatible = "tilcdc,panel";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd7_cape_lcd_pins>;
+				panel-info {
+					ac-bias           = <255>;
+					ac-bias-intrpt    = <0>;
+					dma-burst-sz      = <16>;
+					bpp               = <16>;
+					fdd               = <0x80>;
+					tft-alt-mode      = <0>;
+					stn-565-mode      = <0>;
+					mono-8bit-mode    = <0>;
+					sync-edge         = <0>;
+					sync-ctrl         = <1>;
+					raster-order      = <0>;
+					fifo-th           = <0>;
+				};
+				display-timings {
+					native-mode = <&timing0>;
+					timing0: 800x480 {
+						hactive         = <800>;
+						vactive         = <480>;
+						hback-porch     = <40>;
+						hfront-porch    = <40>;
+						hsync-len       = <48>;
+						vback-porch     = <30>;
+						vfront-porch    = <13>;
+						vsync-len       = <3>;
+						clock-frequency = <30000000>;
+						hsync-active    = <0>;
+						vsync-active    = <0>;
+					};
+				};
+			};
+
+			fb {
+				compatible = "ti,am33xx-tilcdc";
+				reg = <0x4830e000 0x1000>;
+				interrupt-parent = <&intc>;
+				interrupts = <36>;
+				ti,hwmods = "lcdc";
+				ti,power-gpio = <&gpio1 2 0x0>;
+				ti,allow-non-reduced-blanking-modes;
+			};
+
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-LCD7-01-00A4.dts b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
new file mode 100644
index 0000000..3455596
--- /dev/null
+++ b/firmware/capes/BB-BONE-LCD7-01-00A4.dts
@@ -0,0 +1,287 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-LCD7-01";
+	version = "00A4";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.45",	/* lcd: lcd_data0 */
+		"P8.46",	/* lcd: lcd_data1 */
+		"P8.43",	/* lcd: lcd_data2 */
+		"P8.44",	/* lcd: lcd_data3 */
+		"P8.41",	/* lcd: lcd_data4 */
+		"P8.42",	/* lcd: lcd_data5 */
+		"P8.39",	/* lcd: lcd_data6 */
+		"P8.40",	/* lcd: lcd_data7 */
+		"P8.37",	/* lcd: lcd_data8 */
+		"P8.38",	/* lcd: lcd_data9 */
+		"P8.36",	/* lcd: lcd_data10 */
+		"P8.34",	/* lcd: lcd_data11 */
+		"P8.35",	/* lcd: lcd_data12 */
+		"P8.33",	/* lcd: lcd_data13 */
+		"P8.31",	/* lcd: lcd_data14 */
+		"P8.32",	/* lcd: lcd_data15 */
+		"P8.27",	/* lcd: lcd_vsync */
+		"P8.29",	/* lcd: lcd_hsync */
+		"P8.28",	/* lcd: lcd_pclk */
+		"P8.30",	/* lcd: lcd_ac_bias_en */
+		"P9.22",	/* lcd: gpio0_2 */
+		"P9.12",	/* led: gpio1_28 */
+		"P9.14",	/* pwm: ehrpwm1a */
+		"P9.15",	/* keys: gpio1_16 */
+		"P9.23",	/* keys: gpio1_17 */
+		"P9.16",	/* keys: gpio1_19 */
+		"P9.30",	/* keys: gpio3_16 */
+		"P9.21",	/* keys: gpio0_3 */
+		"P9.27",	/* captouch: gpio3_19 */
+		/* the hardware IP uses */
+		"gpio0_2",
+		"gpio1_28",
+		"gpio1_16",
+		"gpio1_17",
+		"gpio1_19",
+		"gpio3_16",
+		"gpio3_19",
+		"gpio0_3",
+		"lcd",
+		"ehrpwm1a";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_lcd7_cape_led_00A4_pins: pinmux_bone_lcd7_cape_led_00A4_pins {
+				pinctrl-single,pins = <
+					0x078 0x2f	/* gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
+				>;
+			};
+
+			pwm_bl_pins: pinmux_pwm_bl_pins {
+				pinctrl-single,pins = <
+					0x48 0x06       /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+
+			bone_lcd7_cape_lcd_pins: pinmux_bone_lcd7_cape_lcd_pins {
+				pinctrl-single,pins = <
+					0x150 0x07	/* spi0_sclk.gpio0_2, OUTPUT | MODE7 - AVDD_EN */
+					0xa0 0x08	/* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa4 0x08	/* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa8 0x08	/* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xac 0x08	/* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb0 0x08	/* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb4 0x08	/* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb8 0x08	/* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xbc 0x08	/* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc0 0x08	/* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc4 0x08	/* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc8 0x08	/* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xcc 0x08	/* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd0 0x08	/* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd4 0x08	/* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd8 0x08	/* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xdc 0x08	/* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xe0 0x00	/* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe4 0x00	/* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe8 0x00	/* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xec 0x00	/* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+
+			bone_lcd7_cape_keys_00A4_pins: pinmux_bone_lcd7_cape_keys_00A4_pins {
+				pinctrl-single,pins = <
+					0x040 0x2f	/* KEY_LEFT gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
+					0x044 0x2f	/* KEY_RIGHT gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
+					0x04c 0x2f 	/* KEY_UP gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
+					0x198 0x2f	/* KEY_DOWN mcasp0_axr0.gpio3_16, INPUT | PULLDIS | MODE7 */
+					0x154 0x2f	/* KEY_ENTER spi0_d0.gpio0_3, INPUT | PULLDIS | MODE7 */
+
+					/* the next one should be in the tsc driver */
+					0x1a4 0x2f	/* TSC_INTn mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
+				>;
+			};
+
+		};
+	};
+
+	fragment@1 {
+		target = <&epwmss1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@2 {
+		target = <&ehrpwm1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@3 {
+		target = <&ocp>;
+
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			backlight {
+				compatible      = "pwm-backlight";
+ 				pinctrl-names   = "default";
+				pinctrl-0       = <&pwm_bl_pins>;
+				status = "okay";
+
+				pwms = <&ehrpwm1 0 500000 0>;
+				pwm-names = "LCD7";
+				brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+				default-brightness-level = <101>; /* index to the array above */
+ 			};
+
+			gpio-leds-cape-lcd7 {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+
+				pinctrl-0 = <&bone_lcd7_cape_led_00A4_pins>;
+
+				lcd7-led0 {
+					label = "lcd7:green:usr0";
+					gpios = <&gpio2 28 0>;
+					linux,default-trigger = "heartbeat";
+					default-state = "off";
+				};
+
+			};
+
+			gpio_keys {
+				compatible = "gpio-keys";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd7_cape_keys_00A4_pins>;
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				button@1 {
+					debounce_interval = <50>;
+					linux,code = <105>;
+					label = "left";
+					gpios = <&gpio2 16 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@2 {
+					debounce_interval = <50>;
+					linux,code = <106>;
+					label = "right";
+					gpios = <&gpio2 17 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@3 {
+					debounce_interval = <50>;
+					linux,code = <103>;
+					label = "up";
+					gpios = <&gpio2 19 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@4 {
+					debounce_interval = <50>;
+					linux,code = <108>;
+					label = "down";
+					gpios = <&gpio4 16 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@5 {
+					debounce_interval = <50>;
+					linux,code = <28>;
+					label = "enter";
+					gpios = <&gpio1 3 0x1>;
+					gpio-key,wakeup;
+				};
+			};
+
+			/* Settings for ThreeFive S9700RTWV35TR / LCD7 cape: */
+			panel {
+				compatible = "tilcdc,panel";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd7_cape_lcd_pins>;
+				panel-info {
+					ac-bias           = <255>;
+					ac-bias-intrpt    = <0>;
+					dma-burst-sz      = <16>;
+					bpp               = <16>;
+					fdd               = <0x80>;
+					tft-alt-mode      = <0>;
+					stn-565-mode      = <0>;
+					mono-8bit-mode    = <0>;
+					sync-edge         = <0>;
+					sync-ctrl         = <1>;
+					raster-order      = <0>;
+					fifo-th           = <0>;
+					invert-pxl-clk;
+				};
+				display-timings {
+					native-mode = <&timing0>;
+					timing0: 800x480 {
+						hactive         = <800>;
+						vactive         = <480>;
+						hback-porch     = <40>;
+						hfront-porch    = <40>;
+						hsync-len       = <48>;
+						vback-porch     = <30>;
+						vfront-porch    = <13>;
+						vsync-len       = <3>;
+						clock-frequency = <30000000>;
+						hsync-active    = <0>;
+						vsync-active    = <0>;
+					};
+				};
+			};
+
+			fb {
+				compatible = "ti,am33xx-tilcdc";
+				reg = <0x4830e000 0x1000>;
+				interrupt-parent = <&intc>;
+				interrupts = <36>;
+				ti,hwmods = "lcdc";
+				ti,power-gpio = <&gpio1 2 0x0>;
+				ti,allow-non-reduced-blanking-modes;
+			};
+
+		};
+	};
+
+       fragment@4 {
+               target = <&i2c2>;
+
+               __overlay__ {
+		       /* needed to avoid gripping by DTC */
+		       #address-cells = <1>;
+		       #size-cells = <0>;
+
+			maxtouch@4a {
+				compatible = "mXT224";
+				reg = <0x4a>;
+				interrupt-parent = <&gpio4>;
+				interrupts = <19 0x0>;
+				atmel,irq-gpio = <&gpio4 19 0>;
+			};
+               };
+       };
+};
diff --git a/firmware/capes/BB-BONE-PRU-01-00A0.dts b/firmware/capes/BB-BONE-PRU-01-00A0.dts
new file mode 100644
index 0000000..9bf2c7a
--- /dev/null
+++ b/firmware/capes/BB-BONE-PRU-01-00A0.dts
@@ -0,0 +1,52 @@
+/*
+* Copyright (C) 2013 Matt Ranostay <mranostay@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.
+*/
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-PRU-01";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.27",	/* pru0: pr1_pru0_pru_r30_5 */
+		/* the hardware IP uses */
+		"pru0";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			pru_gpio_pins: pinmux_pru_gpio_pins {
+				pinctrl-single,pins = <
+					0x1a4 0x0f 	/* P9 27 GPIO3_19: mcasp0_fsr.gpio3[19] | MODE7 | OUTPUT */
+				>;
+			};
+
+			pru_pru_pins: pinmux_pru_pru_pins {
+				pinctrl-single,pins = <
+					0x1a4 0x25	/* mcasp0_fsr.pr1_pru0_pru_r30_5, MODE5 | OUTPUT | PRU */
+				>;
+			};
+		};	
+	};
+
+	fragment@2 {
+		target = <&pruss>;
+		__overlay__ {
+			status = "okay";
+
+			pinctrl-names = "default";
+			pinctrl-0 = <&pru_pru_pins>;
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-PRU-02-00A0.dts b/firmware/capes/BB-BONE-PRU-02-00A0.dts
new file mode 100644
index 0000000..13389c7
--- /dev/null
+++ b/firmware/capes/BB-BONE-PRU-02-00A0.dts
@@ -0,0 +1,68 @@
+/*
+* Copyright (C) 2013 Matt Ranostay <mranostay@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.
+*/
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-PRU-01";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.27",	/* pru0: pr1_pru0_pru_r30_5 */
+		/* the hardware IP uses */
+		"pru0";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			pru_gpio_pins: pinmux_pru_gpio_pins {
+				pinctrl-single,pins = <
+					0x1a4 0x0f 	/* P9 27 GPIO3_19: mcasp0_fsr.gpio3[19] | MODE7 | OUTPUT */
+				>;
+			};
+
+			pru_pru_pins: pinmux_pru_pru_pins {
+				pinctrl-single,pins = <
+					0x1a4 0x25	/* mcasp0_fsr.pr1_pru0_pru_r30_5, MODE5 | OUTPUT | PRU */
+				>;
+			};
+		};	
+	};
+
+	fragment@2 {
+		target = <&ocp>;
+
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			prurproc {
+				compatible = "ti,pru-rproc";
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&pru_pru_pins>;
+
+				ti,hwmods = "pruss";
+				ti,deassert-hard-reset = "pruss", "pruss";
+				reg = <0x4a300000 0x080000>;
+				ti,pintc-offset = <0x20000>;
+				interrupt-parent = <&intc>;
+				status = "okay";
+				interrupts = <20 21 22 23 24 25 26 27>;
+			};
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-PWMT-00A0.dts b/firmware/capes/BB-BONE-PWMT-00A0.dts
new file mode 100644
index 0000000..49747c9
--- /dev/null
+++ b/firmware/capes/BB-BONE-PWMT-00A0.dts
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-PWMT";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.22",	/* pwm: ehrpwm0a */
+		/* the hardware ip uses */
+		"ehrpwm0a";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_test_pins: pinmux_pwm_test_pins {
+				pinctrl-single,pins = <0x150  0x3>; /* spi0_sclk = ehrpwm0A = P9_14 | MODE 3 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&epwmss0>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@2 {
+		target = <&ehrpwm0>;
+		__overlay__ {
+			pinctrl-names	= "default";
+			pinctrl-0	= <&pwm_test_pins>;
+			status = "okay";
+		};
+	};
+
+	fragment@3 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm0 0 500000 1>;
+				pwm-names 	= "PWM0";
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-RS232-00A0.dts b/firmware/capes/BB-BONE-RS232-00A0.dts
new file mode 100644
index 0000000..ad627c5
--- /dev/null
+++ b/firmware/capes/BB-BONE-RS232-00A0.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 Matt Ranostay <mranostay@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.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-RS232";
+	version = "00A0";
+	
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.22",		/* rs232: uart2_rxd */
+		"P9.21",		/* rs232: uart2_txd */
+		/* the hardware IP uses */
+		"uart2";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			uart_pins: pinmux_uart_pins {
+				pinctrl-single,pins = <
+					0x150	0x21	/* spi0_sclk.uart2_rxd | MODE1 | PULL_UP */
+					0x154	0x01	/* spi0_d0.uart2_txd | MODE1 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&uart3>;
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart_pins>;
+		};
+	};
+
+};
diff --git a/firmware/capes/BB-BONE-RST-00A0.dts b/firmware/capes/BB-BONE-RST-00A0.dts
new file mode 100644
index 0000000..12c696f
--- /dev/null
+++ b/firmware/capes/BB-BONE-RST-00A0.dts
@@ -0,0 +1,62 @@
+/*
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-RST";
+	version = "00A0";
+
+	fragment@0 {
+		target = <&ocp>;
+		__overlay__ {
+			test_rctrl: test_reset {
+				compatible = "test-rctrl";
+				#reset-cells = <2>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			test_consumer_rctrl: test_consumer_reset {
+				compatible = "test-consumer-rctrl";
+
+				reset = <&test_rctrl 0 0>;
+				reset-names = "RESET_1";
+			};
+		};
+	};
+
+	fragment@2 {
+		target = <&ocp>;
+		__overlay__ {
+			gpio_rctrl: gpio_reset {
+				compatible = "gpio-rctrl";
+				#reset-cells = <2>;
+
+				gpios = <&gpio2 28 0x1>, <&gpio2 29 0x0>;
+				gpio-names = "HDMI-reset", "eMMC-reset";
+			};
+		};
+	};
+
+	fragment@3 {
+		target = <&ocp>;
+		__overlay__ {
+			gpio_consumer_rctrl:gpio_consumer_reset {
+				compatible = "test-consumer-rctrl";
+
+				reset = <&gpio_rctrl 0 0>, <&gpio_rctrl 1 0>;
+				reset-names = "RESET_1", "RESET_2";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-RST2-00A0.dts b/firmware/capes/BB-BONE-RST2-00A0.dts
new file mode 100644
index 0000000..50b3a60
--- /dev/null
+++ b/firmware/capes/BB-BONE-RST2-00A0.dts
@@ -0,0 +1,27 @@
+/*
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-RST2";
+	version = "00A0";
+
+	fragment@0 {
+		target = <&ocp>;
+		__overlay__ {
+			emmc_reset_consumer_rctrl: emmc_reset_consumer {
+				compatible = "test-consumer-rctrl";
+
+				reset = <&rstctl 0 0>;
+				reset-names = "eMMC_RSTn-CONSUMER";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-SERL-01-00A1.dts b/firmware/capes/BB-BONE-SERL-01-00A1.dts
new file mode 100644
index 0000000..93b1bfc
--- /dev/null
+++ b/firmware/capes/BB-BONE-SERL-01-00A1.dts
@@ -0,0 +1,45 @@
+/*
+* Copyright (C) 2013 Martin Gysel <me@bearsh.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.
+*/
+/dts-v1/;
+/plugin/;
+
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+	part-number = "BB-BONE-SERL-01";
+	version = "00A1";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.26",		/* dcan1: dcan1_tx */
+		"P9.24",		/* dcan1: dcan1_rx */
+		/* the hardware IP uses */
+		"dcan1";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			bone_serl_01_dcan1_pins: bone_serl_01_dcan1_pins {
+				pinctrl-single,pins = <
+					0x180 0x02      /* uart1_rxd.d_can1_tx", OUTPUT | MODE2 */
+					0x184 0x32      /* uart1_txd.d_can1_rx", INPUT_PULLUP | MODE2 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&dcan1>;
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bone_serl_01_dcan1_pins>;
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-SERL-03-00A1.dts b/firmware/capes/BB-BONE-SERL-03-00A1.dts
new file mode 100644
index 0000000..47d9890
--- /dev/null
+++ b/firmware/capes/BB-BONE-SERL-03-00A1.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * RS232 cape for the default configuration on UART2
+ * Use one of the BB-UART* examples if you modify the default
+ * configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-SERL-03";
+	version = "00A1";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.21",	/* uart2_txd */
+		"P9.22",	/* uart2_rxd */
+		/* the hardware ip uses */
+		"uart2";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			bb_uart2_pins: pinmux_bb_uart2_pins {
+				pinctrl-single,pins = <
+					0x150 0x21	/* spi0_sclk.uart2_rxd | MODE1 */
+					0x154 0x01	/* spi0_d0.uart2_txd | MODE1 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&uart3>;	/* really uart2 */
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bb_uart2_pins>;
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONE-eMMC1-01-00A0.dts b/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
new file mode 100644
index 0000000..44c01fe
--- /dev/null
+++ b/firmware/capes/BB-BONE-eMMC1-01-00A0.dts
@@ -0,0 +1,68 @@
+/*
+* 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-eMMC1-01";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.21",	/* mmc1: mmc1_clk */
+		"P8.20",	/* mmc1: mmc1_cmd */
+		"P8.25",	/* mmc1: mmc1_dat0 */
+		"P8.24",	/* mmc1: mmc1_dat1 */
+		"P8.5",		/* mmc1: mmc1_dat2 */
+		"P8.6",		/* mmc1: mmc1_dat3 */
+		"P8.23",	/* mmc1: mmc1_dat4 */
+		"P8.22",	/* mmc1: mmc1_dat5 */
+		"P8.3",		/* mmc1: mmc1_dat6 */
+		"P8.4",		/* mmc1: mmc1_dat7 */
+		/* the hardware IP uses */
+		"mmc1";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			emmc2_pins: pinmux_emmc2_pins {
+				pinctrl-single,pins = <
+					0x80 0x32	/* gpmc_csn1.mmc1_clk, INPUT_PULLUP | MODE2 */
+					0x84 0x32	/* gpmc_csn1.mmc1_cmd, INPUT_PULLUP | MODE2 */
+					0x00 0x31	/* gpmc_ad0.mmc1_dat0, INPUT_PULLUP | MODE1 */
+					0x04 0x31	/* gpmc_ad1.mmc1_dat1, INPUT_PULLUP | MODE1 */
+					0x08 0x31	/* gpmc_ad2.mmc1_dat2, INPUT_PULLUP | MODE1 */
+					0x0c 0x31	/* gpmc_ad3.mmc1_dat3, INPUT_PULLUP | MODE1 */
+					0x10 0x31	/* gpmc_ad4.mmc1_dat4, INPUT_PULLUP | MODE1 */
+					0x14 0x31	/* gpmc_ad5.mmc1_dat5, INPUT_PULLUP | MODE1 */
+					0x18 0x31	/* gpmc_ad6.mmc1_dat6, INPUT_PULLUP | MODE1 */
+					0x1c 0x31	/* gpmc_ad7.mmc1_dat7, INPUT_PULLUP | MODE1 */
+				>;
+			};
+		};
+	};
+	fragment@1 {
+		target = <&mmc2>;
+		__overlay__ {
+			pinctrl-names = "default";
+			pinctrl-0 = <&emmc2_pins>;	/* wrong numbering */
+			vmmc-supply = <&ldo3_reg>;
+			bus-width = <8>;
+			ti,non-removable;
+			status = "okay";
+			ti,vcc-aux-disable-is-sleep;
+
+			reset = <&rstctl 0 0>;
+			reset-names = "eMMC_RSTn";
+		};
+	};
+};
diff --git a/firmware/capes/BB-BONELT-BT-00A0.dts b/firmware/capes/BB-BONELT-BT-00A0.dts
new file mode 100644
index 0000000..dc3b386
--- /dev/null
+++ b/firmware/capes/BB-BONELT-BT-00A0.dts
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONELT-BT";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.43",		/* bt: gpio2_8 */
+		/* the hardware IP uses */
+		"gpio2_8";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_bt_cape_key_pins: pinmux_bone_bt_cape_key_pins {
+				pinctrl-single,pins = <
+					0x0a8 0x2f /* P8.43 lcd_data2.gpio2[8]  DISABLE internal pullup  */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			bt_gpio_key {
+				compatible = "gpio-keys";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_bt_cape_key_pins>;
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				button@1 {
+					debounce_interval = <0>;
+					linux,code = <28>;
+					label = "enter";
+					gpios = <&gpio3 8 0x0>;
+				};
+			};
+		};
+	};
+};
diff --git a/firmware/capes/BB-GPIOHELP-00A0.dts b/firmware/capes/BB-GPIOHELP-00A0.dts
new file mode 100644
index 0000000..ba2a74b
--- /dev/null
+++ b/firmware/capes/BB-GPIOHELP-00A0.dts
@@ -0,0 +1,66 @@
+/*
+* Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-GPIOHELP";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.27",	/* gpio */
+		"P9.28",	/* gpio */
+		/* the hardware IP uses */
+		"gpio3_19", "gpio3_17";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			gpio_helper_pins: pinmux_gpio_helper_pins {
+				pinctrl-single,pins = <
+					0x1a4 0x0f 	/* P9 27 GPIO3_19: mcasp0_fsr.gpio3_19 | MODE7 | OUTPUT */
+					0x19c 0x2f	/* P9 28 SPI1_CS0: mcasp0_ahclkr.gpio3_17 | MODE7 | INPUT */
+				>;
+			};
+		};	
+	};
+
+	fragment@2 {
+		target = <&ocp>;
+		__overlay__ {
+
+			gpio_helper {
+				compatible = "gpio-of-helper";
+				status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <&gpio_helper_pins>;
+
+				/* declare your gpios */
+				test_led {
+					gpio-name = "test_led";
+					gpio = <&gpio4 19 0x00>;	/* gpio4 is gpio3 */
+					output;
+					init-high;
+				};
+
+				test_input {
+					gpio-name = "test_input";
+					gpio = <&gpio4 17 0x00>;	/* gpio4 is gpio3 */
+					input;
+					count-rising-edge;
+					count-falling-edge;
+				};
+			};
+		};
+	};
+};
diff --git a/firmware/capes/BB-I2C1-00A0.dts b/firmware/capes/BB-I2C1-00A0.dts
new file mode 100644
index 0000000..9e74f26
--- /dev/null
+++ b/firmware/capes/BB-I2C1-00A0.dts
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * Virtual cape for I2C1 on connector pins P9.17 P9.18
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-I2C1";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.18",	/* i2c1_sda */
+		"P9.17",	/* i2c1_scl */
+		/* the hardware ip uses */
+		"i2c1";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			bb_i2c1_pins: pinmux_bb_i2c1_pins {
+				pinctrl-single,pins = <
+					0x158 0x72	/* spi0_d1.i2c1_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
+					0x15c 0x72	/* spi0_cs0.i2c1_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&i2c1>;	/* i2c1 is numbered correctly */
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bb_i2c1_pins>;
+
+			/* this is the configuration part */
+			clock-frequency = <100000>;	
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* add any i2c devices on the bus here */
+
+			// commented out example of a touchscreen (taken from BB-BONE-LCD7-01-00A4) */
+			// maxtouch@4a {
+			//	compatible = "mXT224";
+			//	reg = <0x4a>;
+			//	interrupt-parent = <&gpio4>;
+			//	interrupts = <19 0x0>;
+			//	atmel,irq-gpio = <&gpio4 19 0>;
+			// };
+		};
+	};
+};
diff --git a/firmware/capes/BB-I2C1A1-00A0.dts b/firmware/capes/BB-I2C1A1-00A0.dts
new file mode 100644
index 0000000..4a2b1bd
--- /dev/null
+++ b/firmware/capes/BB-I2C1A1-00A0.dts
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * Virtual cape for I2C1 on connector pins P9.26 P9.24 (ALT config #1)
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-I2C1A1";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.26",	/* i2c1_sda */
+		"P9.24",	/* i2c1_scl */
+		/* the hardware ip uses */
+		"i2c1";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			bb_i2c1a1_pins: pinmux_bb_i2c1a1_pins {
+				pinctrl-single,pins = <
+					0x180 0x73	/* uart1_rxd.i2c1_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+					0x184 0x73	/* uart1_txdi2c1_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&i2c1>;	/* i2c1 is numbered correctly */
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bb_i2c1a1_pins>;
+
+			/* this is the configuration part */
+			clock-frequency = <100000>;	
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* add any i2c devices on the bus here */
+
+			// commented out example of a touchscreen (taken from BB-BONE-LCD7-01-00A4) */
+			// maxtouch@4a {
+			//	compatible = "mXT224";
+			//	reg = <0x4a>;
+			//	interrupt-parent = <&gpio4>;
+			//	interrupts = <19 0x0>;
+			//	atmel,irq-gpio = <&gpio4 19 0>;
+			// };
+		};
+	};
+};
diff --git a/firmware/capes/BB-SPI0-00A0.dts b/firmware/capes/BB-SPI0-00A0.dts
new file mode 100644
index 0000000..547efce
--- /dev/null
+++ b/firmware/capes/BB-SPI0-00A0.dts
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * Virtual cape for SPI0 on connector pins P9.22 P9.21 P9.18 P9.17
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-SPI0";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.17",	/* spi0_cs0 */
+		"P9.18",	/* spi0_d1 */
+		"P9.21",	/* spi0_d0 */
+		"P9.22",	/* spi0_sclk */
+		/* the hardware ip uses */
+		"spi0";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			/* default state has all gpios released and mode set to uart1 */
+			bb_spi0_pins: pinmux_bb_spi0_pins {
+				pinctrl-single,pins = <
+					0x150 0x30	/* spi0_sclk.spi0_sclk, INPUT_PULLUP | MODE0 */
+					0x154 0x30	/* spi0_d0.spi0_d0, INPUT_PULLUP | MODE0 */
+					0x158 0x10	/* spi0_d1.spi0_d1, OUTPUT_PULLUP | MODE0 */
+					0x15c 0x10	/* spi0_cs0.spi0_cs0, OUTPUT_PULLUP | MODE0 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&spi0>;	/* spi0 is numbered correctly */
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bb_spi0_pins>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* add any spi devices connected here */
+			/* note that you can do direct SPI via spidev now */
+
+			// commented out example of an adafruit 1.8" TFT display
+			// from firmare/capes/cape-bone-adafruit-lcd-00A0.dts
+			// lcd@0 {
+			//	#address-cells = <1>;
+			//	#size-cells = <0>;
+			//
+			//	compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
+			//	reg = <0>;
+			//
+			//	spi-max-frequency = <8000000>;
+			//	spi-cpol;
+			//	spi-cpha;
+			//
+			//	pinctrl-names = "default";
+			//	pinctrl-0 = <&bone_adafruit_lcd_pins>;
+			//
+			//	st7735-rst = <&gpio4 19 0>;
+			//	st7735-dc = <&gpio4 21 0>;
+			// };
+		};
+	};
+};
diff --git a/firmware/capes/BB-SPI1-00A0.dts b/firmware/capes/BB-SPI1-00A0.dts
new file mode 100644
index 0000000..1ead983
--- /dev/null
+++ b/firmware/capes/BB-SPI1-00A0.dts
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * Virtual cape for SPI1 on connector pins P9.29 P9.31 P9.30 P9.28
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-SPI1";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.31",	/* spi1_sclk */
+		"P9.29",	/* spi1_d0 */
+		"P9.30",	/* spi1_d1 */
+		"P9.28",	/* spi1_cs0 */
+		// "P9.42",	/* spi1_cs1 */
+		/* the hardware ip uses */
+		"spi1";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			/* default state has all gpios released and mode set to uart1 */
+			bb_spi1_pins: pinmux_bb_spi1_pins {
+				pinctrl-single,pins = <
+					0x190 0x33	/* mcasp0_aclkx.spi1_sclk, INPUT_PULLUP | MODE3 */
+					0x194 0x33	/* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
+					0x198 0x13	/* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
+					0x19c 0x13	/* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+					// 0x164 0x12	/* eCAP0_in_PWM0_out.spi1_cs1 OUTPUT_PULLUP | MODE2 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&spi1>;	/* spi1 is numbered correctly */
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bb_spi1_pins>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* add any spi devices connected here */
+			/* note that you can do direct SPI via spidev now */
+
+			// commented out example of an adafruit 1.8" TFT display
+			// from firmare/capes/cape-bone-adafruit-lcd-00A0.dts
+			// lcd@0 {
+			//	#address-cells = <1>;
+			//	#size-cells = <0>;
+			//
+			//	compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
+			//	reg = <0>;
+			//
+			//	spi-max-frequency = <8000000>;
+			//	spi-cpol;
+			//	spi-cpha;
+			//
+			//	pinctrl-names = "default";
+			//	pinctrl-0 = <&bone_adafruit_lcd_pins>;
+			//
+			//	st7735-rst = <&gpio4 19 0>;
+			//	st7735-dc = <&gpio4 21 0>;
+			// };
+		};
+	};
+};
diff --git a/firmware/capes/BB-SPI1A1-00A0.dts b/firmware/capes/BB-SPI1A1-00A0.dts
new file mode 100644
index 0000000..ba98e73
--- /dev/null
+++ b/firmware/capes/BB-SPI1A1-00A0.dts
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * Virtual cape for SPI1 (ALT #1) on connector pins 
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-SPI1";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.42",	/* spi1_sclk */
+		"P9.29",	/* spi1_d0 */
+		"P9.30",	/* spi1_d1 */
+		"P9.20",	/* spi1_cs0 */
+		/* the hardware ip uses */
+		"spi1";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			/* default state has all gpios released and mode set to uart1 */
+			bb_spi1_pins: pinmux_bb_spi1_pins {
+				pinctrl-single,pins = <
+					0x164 0x34	/* eCAP0_in_PWM0_out.spi1_sclk, INPUT_PULLUP | MODE4 */
+							/* NOTE: P9.42 is connected to two pads */
+					// 0x1A0 0x27	/* set the other pad to gpio input */
+					0x194 0x33	/* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
+					0x198 0x13	/* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
+					0x178 0x14	/* uart1_ctsn.spi1_cs0, OUTPUT_PULLUP | MODE4 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&spi1>;	/* spi1 is numbered correctly */
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bb_spi1_pins>;
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* add any spi devices connected here */
+			/* note that you can do direct SPI via spidev now */
+
+			// commented out example of an adafruit 1.8" TFT display
+			// from firmare/capes/cape-bone-adafruit-lcd-00A0.dts
+			// lcd@0 {
+			//	#address-cells = <1>;
+			//	#size-cells = <0>;
+			//
+			//	compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
+			//	reg = <0>;
+			//
+			//	spi-max-frequency = <8000000>;
+			//	spi-cpol;
+			//	spi-cpha;
+			//
+			//	pinctrl-names = "default";
+			//	pinctrl-0 = <&bone_adafruit_lcd_pins>;
+			//
+			//	st7735-rst = <&gpio4 19 0>;
+			//	st7735-dc = <&gpio4 21 0>;
+			// };
+		};
+	};
+};
diff --git a/firmware/capes/BB-UART1-00A0.dts b/firmware/capes/BB-UART1-00A0.dts
new file mode 100644
index 0000000..ce2b3d1
--- /dev/null
+++ b/firmware/capes/BB-UART1-00A0.dts
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * Virtual cape for UART1 on connector pins P9.24 P9.26
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-UART1";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.24",	/* uart1_txd */
+		"P9.26",	/* uart1_rxd */
+		/* the hardware ip uses */
+		"uart1";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			bb_uart1_pins: pinmux_bb_uart1_pins {
+				pinctrl-single,pins = <
+					0x184 0x20 /* P9.24 uart1_txd.uart1_txd  OUTPUT  */
+					0x180 0x20 /* P9.26 uart1_rxd.uart1_rxd  INPUT  */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&uart2>;	/* really uart1 */
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bb_uart1_pins>;
+		};
+	};
+};
diff --git a/firmware/capes/BB-UART2-00A0.dts b/firmware/capes/BB-UART2-00A0.dts
new file mode 100644
index 0000000..7534495
--- /dev/null
+++ b/firmware/capes/BB-UART2-00A0.dts
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * Virtual cape for UART2 on connector pins P9.21 P9.22
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-UART2";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.21",	/* uart2_txd */
+		"P9.22",	/* uart2_rxd */
+		/* the hardware ip uses */
+		"uart2";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			bb_uart2_pins: pinmux_bb_uart2_pins {
+				pinctrl-single,pins = <
+					0x150 0x21	/* spi0_sclk.uart2_rxd | MODE1 */
+					0x154 0x01	/* spi0_d0.uart2_txd | MODE1 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&uart3>;	/* really uart2 */
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bb_uart2_pins>;
+		};
+	};
+};
diff --git a/firmware/capes/BB-UART4-00A0.dts b/firmware/capes/BB-UART4-00A0.dts
new file mode 100644
index 0000000..cfd7947
--- /dev/null
+++ b/firmware/capes/BB-UART4-00A0.dts
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * Virtual cape for UART4 on connector pins P9.13 P9.11
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-UART4";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.13",	/* uart4_txd */
+		"P9.11",	/* uart4_rxd */
+		/* the hardware ip uses */
+		"uart4";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			bb_uart4_pins: pinmux_bb_uart4_pins {
+				pinctrl-single,pins = <
+					0x070 0x26	/* gpmc_wait0.uart4_rxd | MODE6 */
+					0x074 0x06	/* gpmc_wpn.uart4_txd | MODE6 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&uart5>;	/* really uart4 */
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bb_uart4_pins>;
+		};
+	};
+};
diff --git a/firmware/capes/BB-UART5-00A0.dts b/firmware/capes/BB-UART5-00A0.dts
new file mode 100644
index 0000000..e067068
--- /dev/null
+++ b/firmware/capes/BB-UART5-00A0.dts
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * Virtual cape for UART5 on connector pins P9.37 P8.38
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-UART5";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.37",	/* uart5_txd */
+		"P8.38",	/* uart5_rxd */
+		/* the hardware ip uses */
+		"uart5";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			bb_uart5_pins: pinmux_bb_uart5_pins {
+				pinctrl-single,pins = <
+					/* the uart pins */
+					0x0C4 0x24	/* lcd_data9.uart5_rxd | MODE4 */
+					0x0C0 0x04	/* lcd_data8.uart5_txd | MODE4 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&uart6>;	/* really uart5 */
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bb_uart5_pins>;
+		};
+	};
+};
diff --git a/firmware/capes/TT3201-001-01.dts b/firmware/capes/TT3201-001-01.dts
new file mode 100644
index 0000000..d1f950c
--- /dev/null
+++ b/firmware/capes/TT3201-001-01.dts
@@ -0,0 +1,134 @@
+/*
+* Copyright (C) 2013 Tower Technologies
+* Written by Alessandro Zummo <a.zummo@towertech.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.
+*/
+/dts-v1/;
+/plugin/;
+
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+	part-number = "TT3201-001";
+	version = "01";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.27",	/* spi irq: gpio3_19 */
+		"P9.25",	/* spi irq: gpio3_21 */
+		"P9.31",	/* spi: spi1_sclk */
+		"P9.29",	/* spi: spi1_d0 */
+		"P9.30",	/* spi: spi1_d1 */
+		"P9.28",	/* spi: spi1_cs0 */
+		"P9.42",	/* spi: spi1_cs1 */
+		"P9.26",	/* dcan1: dcan1_tx */
+		"P9.24",	/* dcan1: dcan1_rx */
+		/* the hardware IP uses */
+		"gpio3_19",
+		"gpio3_21",
+		"spi1",
+		"dcan1";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_tt3201_dcan1_pins: bone_tt3201_dcan1_pins {
+				pinctrl-single,pins = <
+					0x180 0x02      /* uart1_rxd.d_can1_tx", OUTPUT | MODE2 */
+					0x184 0x32      /* uart1_txd.d_can1_rx", INPUT_PULLUP | MODE2 */
+				>;
+			};
+
+			bone_tt3201_spi1_pins: pinmux_bone_tt3201_spi1_pins {
+				pinctrl-single,pins = <
+					0x190 0x33      /* mcasp0_aclkx.spi1_sclk, RX_ENABLED | PULLUP | MODE3 */
+					0x194 0x33      /* mcasp0_fsx.spi1_d0, RX_ENABLED | PULLUP | MODE3 */
+					0x198 0x13      /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
+					0x19c 0x13      /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+					0x164 0x12	/* ecap0_in_pwm0_out.spi1_cs1, OUTPUT_PULLUP | MODE2 */
+				>;
+			};
+
+			bone_tt3201_mcp2515_0_pins: pinmux_bone_tt3201_0_mcp2515_pins {
+				pinctrl-single,pins = <
+					0x1a4 0x37	/* mcasp0_fsr.gpio3_19, RX_ENABLED | PULLUP | MODE7 */
+				>;
+			};
+
+			bone_tt3201_mcp2515_1_pins: pinmux_bone_tt3201_1_mcp2515_pins {
+				pinctrl-single,pins = <
+					0x1ac 0x37      /* mcasp0_ahclkx.gpio3_21, RX_ENABLED | PULLUP | MODE7 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+	      target = <&spi1>;
+
+		__overlay__ {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			status	  = "okay";
+			pinctrl-names   = "default";
+			pinctrl-0       = <&bone_tt3201_spi1_pins>;
+
+			cs-gpios = <&gpio4 17 0>, <&gpio1 7 0>;
+
+			mcp2515@0 {
+
+				compatible = "microchip,mcp2515";
+				reg = <1>; /* cs1 */
+				mode = <0>;
+
+				spi-max-frequency = <10000000>;
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_tt3201_mcp2515_1_pins>;
+
+				interrupt-parent = <&gpio4>;
+				interrupts = <21>;
+
+				mcp251x,oscillator-frequency = <16000000>;
+				mcp251x,irq-gpios = <&gpio4 21 0>;
+				mcp251x,stay-awake = <1>;
+			};
+
+			mcp2515@1 {
+
+				compatible = "microchip,mcp2515";
+				reg = <0>; /* cs0 */
+				mode = <0>;
+
+				spi-max-frequency = <10000000>;
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_tt3201_mcp2515_0_pins>;
+
+				interrupt-parent = <&gpio4>;
+				interrupts = <19>;
+
+				mcp251x,oscillator-frequency = <16000000>;
+				mcp251x,irq-gpios = <&gpio4 19 0>;
+				mcp251x,stay-awake = <1>;
+				mcp251x,enable-clkout = <1>;
+			};
+		};
+	};
+
+	fragment@2 {
+		target = <&dcan1>;
+		__overlay__ {
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bone_tt3201_dcan1_pins>;
+		};
+	};
+};
+
diff --git a/firmware/capes/am33xx_pwm-00A0.dts b/firmware/capes/am33xx_pwm-00A0.dts
new file mode 100644
index 0000000..fa8d770
--- /dev/null
+++ b/firmware/capes/am33xx_pwm-00A0.dts
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "test1";
+	version = "00A0";
+
+	fragment@0 {
+		target = <&epwmss0>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@1 {
+		target = <&ehrpwm0>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@2 {
+		target = <&ecap0>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@3 {
+		target = <&epwmss1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@4 {
+		target = <&ehrpwm1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@5 {
+		target = <&epwmss2>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@6 {
+		target = <&ehrpwm2>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@7 {
+		target = <&ecap2>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P8_13-00A0.dts b/firmware/capes/bone_pwm_P8_13-00A0.dts
new file mode 100644
index 0000000..dde034e
--- /dev/null
+++ b/firmware/capes/bone_pwm_P8_13-00A0.dts
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P8_13";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.13",		/* pwm: ehrpwm2B */
+		/* the hardware IP uses */
+		"ehrpwm2B";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P8_13: pinmux_pwm_P8_13_pins {
+				pinctrl-single,pins = <0x024  0x4>; /* P8_13 (ZCZ ball T10) | MODE 4 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P8_13 {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm2 1 500000 1>;
+				pwm-names 	= "PWM_P8_13";
+
+				pinctrl-names	= "default";
+				pinctrl-0	= <&pwm_P8_13>;
+
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P8_19-00A0.dts b/firmware/capes/bone_pwm_P8_19-00A0.dts
new file mode 100644
index 0000000..ea52f65
--- /dev/null
+++ b/firmware/capes/bone_pwm_P8_19-00A0.dts
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P8_19";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.19",		/* pwm: ehrpwm2A */
+		/* the hardware IP uses */
+		"ehrpwm2A";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P8_19: pinmux_pwm_P8_19_pins {
+				pinctrl-single,pins = <0x020  0x4>; /* P8_19 (ZCZ ball U10) | MODE 4 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P8_19 {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm2 0 500000 1>;
+				pwm-names 	= "PWM_P8_19";
+
+				pinctrl-names	= "default";
+				pinctrl-0	= <&pwm_P8_19>;
+
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P8_34-00A0.dts b/firmware/capes/bone_pwm_P8_34-00A0.dts
new file mode 100644
index 0000000..d7b22bd
--- /dev/null
+++ b/firmware/capes/bone_pwm_P8_34-00A0.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P8_34";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.34",		/* pwm: ehrpwm1B */
+		/* the hardware IP uses */
+		"ehrpwm1B";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P8_34: pinmux_pwm_P8_34_pins {
+				pinctrl-single,pins = <0x0cc  0x2>; /* P8_34 (ZCZ ball U4) | MODE 2 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P8_34 {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm1 1 500000 1>;
+				pwm-names 	= "PWM_P8_34";
+			    pinctrl-names	= "default";
+			    pinctrl-0	= <&pwm_P8_34>;
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P8_36-00A0.dts b/firmware/capes/bone_pwm_P8_36-00A0.dts
new file mode 100644
index 0000000..ab1f436
--- /dev/null
+++ b/firmware/capes/bone_pwm_P8_36-00A0.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P8_36";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.36",		/* pwm: ehrpwm1A */
+		/* the hardware IP uses */
+		"ehrpwm1A";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P8_36: pinmux_pwm_P8_36_pins {
+				pinctrl-single,pins = <0x0c8  0x2>; /* P8_36 (ZCZ ball U3) | MODE 2 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P8_36 {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm1 0 500000 1>;
+				pwm-names 	= "PWM_P8_36";
+			    pinctrl-names	= "default";
+			    pinctrl-0	= <&pwm_P8_36>;
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P8_45-00A0.dts b/firmware/capes/bone_pwm_P8_45-00A0.dts
new file mode 100644
index 0000000..a612209
--- /dev/null
+++ b/firmware/capes/bone_pwm_P8_45-00A0.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P8_45";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.45",		/* pwm: ehrpwm2A */
+		/* the hardware IP uses */
+		"ehrpwm2A";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P8_45: pinmux_pwm_P8_45_pins {
+				pinctrl-single,pins = <0x0a0  0x3>; /* P8_45 (ZCZ ball R1) | MODE 3 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P8_45 {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm2 0 500000 1>;
+				pwm-names 	= "PWM_P8_45";
+			    pinctrl-names	= "default";
+			    pinctrl-0	= <&pwm_P8_45>;
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P8_46-00A0.dts b/firmware/capes/bone_pwm_P8_46-00A0.dts
new file mode 100644
index 0000000..45e4432
--- /dev/null
+++ b/firmware/capes/bone_pwm_P8_46-00A0.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P8_46";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.46",		/* pwm: ehrpwm2B */
+		/* the hardware IP uses */
+		"ehrpwm2B";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P8_46: pinmux_pwm_P8_46_pins {
+				pinctrl-single,pins = <0x0a4  0x3>; /* P8_46 (ZCZ ball R2) | MODE 3 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P8_46 {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm2 1 500000 1>;
+				pwm-names 	= "PWM_P8_46";
+			    pinctrl-names	= "default";
+			    pinctrl-0	= <&pwm_P8_46>;
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P9_14-00A0.dts b/firmware/capes/bone_pwm_P9_14-00A0.dts
new file mode 100644
index 0000000..23c3c89
--- /dev/null
+++ b/firmware/capes/bone_pwm_P9_14-00A0.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P9_14";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.14",		/* pwm: ehrpwm1A */
+		/* the hardware IP uses */
+		"ehrpwm1A";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P9_14: pinmux_pwm_P9_14_pins {
+				pinctrl-single,pins = <0x048  0x6>; /* P9_14 (ZCZ ball U14) | MODE 6 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P9_14 {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm1 0 500000 1>;
+				pwm-names 	= "PWM_P9_14";
+			    pinctrl-names	= "default";
+			    pinctrl-0	= <&pwm_P9_14>;
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P9_16-00A0.dts b/firmware/capes/bone_pwm_P9_16-00A0.dts
new file mode 100644
index 0000000..fdb7258
--- /dev/null
+++ b/firmware/capes/bone_pwm_P9_16-00A0.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P9_16";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.16",		/* pwm: ehrpwm1B */
+		/* the hardware IP uses */
+		"ehrpwm1B";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P9_16: pinmux_pwm_P9_16_pins {
+				pinctrl-single,pins = <0x04c  0x6>; /* P9_16 (ZCZ ball T14) | MODE 6 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P9_16 {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm1 1 500000 1>;
+				pwm-names 	= "PWM_P9_16";
+			    pinctrl-names	= "default";
+			    pinctrl-0	= <&pwm_P9_16>;
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P9_21-00A0.dts b/firmware/capes/bone_pwm_P9_21-00A0.dts
new file mode 100644
index 0000000..485ffd7
--- /dev/null
+++ b/firmware/capes/bone_pwm_P9_21-00A0.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P9_21";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.21",		/* pwm: ehrpwm0B */
+		/* the hardware IP uses */
+		"ehrpwm0B";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P9_21: pinmux_pwm_P9_21_pins {
+				pinctrl-single,pins = <0x154  0x3>; /* P9_21 (ZCZ ball B17) | MODE 3 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P9_21 {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm0 1 500000 1>;
+				pwm-names 	= "PWM_P9_21";
+			    pinctrl-names	= "default";
+			    pinctrl-0	= <&pwm_P9_21>;
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P9_22-00A0.dts b/firmware/capes/bone_pwm_P9_22-00A0.dts
new file mode 100644
index 0000000..111e6e4
--- /dev/null
+++ b/firmware/capes/bone_pwm_P9_22-00A0.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P9_22";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.22",		/* pwm: ehrpwm0A */
+		/* the hardware IP uses */
+		"ehrpwm0A";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P9_22: pinmux_pwm_P9_22_pins {
+				pinctrl-single,pins = <0x150  0x3>; /* P9_22 (ZCZ ball A17) | MODE 3 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P9_22 {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm0 0 500000 1>;
+				pwm-names 	= "PWM_P9_22";
+			    pinctrl-names	= "default";
+			    pinctrl-0	= <&pwm_P9_22>;
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P9_28-00A0.dts b/firmware/capes/bone_pwm_P9_28-00A0.dts
new file mode 100644
index 0000000..73c59c9
--- /dev/null
+++ b/firmware/capes/bone_pwm_P9_28-00A0.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P9_28";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.28",		/* pwm: eCAP2_in_PWM2_out */
+		/* the hardware IP uses */
+		"eCAP2_in_PWM2_out";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P9_28: pinmux_pwm_P9_28_pins {
+				pinctrl-single,pins = <0x19c  0x4>; /* P9_28 (ZCZ ball C12) | MODE 4 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P9_28 {
+				compatible	= "pwm_test";
+				pwms 		= <&ecap2 0 500000 1>;
+				pwm-names 	= "PWM_P9_28";
+			    pinctrl-names	= "default";
+			    pinctrl-0	= <&pwm_P9_28>;
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P9_29-00A0.dts b/firmware/capes/bone_pwm_P9_29-00A0.dts
new file mode 100644
index 0000000..16a3533
--- /dev/null
+++ b/firmware/capes/bone_pwm_P9_29-00A0.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P9_29";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.29",		/* pwm: ehrpwm0B */
+		/* the hardware IP uses */
+		"ehrpwm0B";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P9_29: pinmux_pwm_P9_29_pins {
+				pinctrl-single,pins = <0x194  0x1>; /* P9_29 (ZCZ ball B13) | MODE 1 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P9_29 {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm0 1 500000 1>;
+				pwm-names 	= "PWM_P9_29";
+			    pinctrl-names	= "default";
+			    pinctrl-0	= <&pwm_P9_29>;
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P9_31-00A0.dts b/firmware/capes/bone_pwm_P9_31-00A0.dts
new file mode 100644
index 0000000..467c993
--- /dev/null
+++ b/firmware/capes/bone_pwm_P9_31-00A0.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P9_31";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.31",		/* pwm: ehrpwm0A */
+		/* the hardware IP uses */
+		"ehrpwm0A";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P9_31: pinmux_pwm_P9_31_pins {
+				pinctrl-single,pins = <0x190  0x1>; /* P9_31 (ZCZ ball A13) | MODE 1 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P9_31 {
+				compatible	= "pwm_test";
+				pwms 		= <&ehrpwm0 0 500000 1>;
+				pwm-names 	= "PWM_P9_31";
+			    pinctrl-names	= "default";
+			    pinctrl-0	= <&pwm_P9_31>;
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/bone_pwm_P9_42-00A0.dts b/firmware/capes/bone_pwm_P9_42-00A0.dts
new file mode 100644
index 0000000..90e1df8
--- /dev/null
+++ b/firmware/capes/bone_pwm_P9_42-00A0.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "bone_pwm_P9_42";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.42",		/* pwm: eCAP0_in_PWM0_out */
+		/* the hardware IP uses */
+		"eCAP0_in_PWM0_out";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_P9_42: pinmux_pwm_P9_42_pins {
+				pinctrl-single,pins = <0x164  0x0>; /* P9_42 (ZCZ ball C18) | MODE 0 */
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			pwm_test_P9_42 {
+				compatible	= "pwm_test";
+				pwms 		= <&ecap0 0 500000 1>;
+				pwm-names 	= "PWM_P9_42";
+			    pinctrl-names	= "default";
+			    pinctrl-0	= <&pwm_P9_42>;
+				enabled		= <1>;
+				duty		= <0>;
+				status 		= "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-2g-emmc1.dts b/firmware/capes/cape-bone-2g-emmc1.dts
new file mode 100644
index 0000000..90067d5
--- /dev/null
+++ b/firmware/capes/cape-bone-2g-emmc1.dts
@@ -0,0 +1,71 @@
+/*
+* 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone-black";
+	ti,on-baseboard;
+
+	/* identification */
+	part-number = "*";	/* any part number */
+	version = "*";		/* any version */
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.21",	/* mmc1: mmc1_clk */
+		"P8.20",	/* mmc1: mmc1_cmd */
+		"P8.25",	/* mmc1: mmc1_dat0 */
+		"P8.24",	/* mmc1: mmc1_dat1 */
+		"P8.5",		/* mmc1: mmc1_dat2 */
+		"P8.6",		/* mmc1: mmc1_dat3 */
+		"P8.23",	/* mmc1: mmc1_dat4 */
+		"P8.22",	/* mmc1: mmc1_dat5 */
+		"P8.3",		/* mmc1: mmc1_dat6 */
+		"P8.4",		/* mmc1: mmc1_dat7 */
+		/* the hardware IP uses */
+		"mmc1",
+		/* the reset pin */
+		"eMMC_RSTn";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			emmc2_pins: pinmux_emmc2_pins {
+				pinctrl-single,pins = <
+					0x80 0x32	/* gpmc_csn1.mmc1_clk, INPUT_PULLUP | MODE2 */
+					0x84 0x32	/* gpmc_csn2.mmc1_cmd, INPUT_PULLUP | MODE2 */
+					0x00 0x31	/* gpmc_ad0.mmc1_dat0, INPUT_PULLUP | MODE1 */
+					0x04 0x31	/* gpmc_ad1.mmc1_dat1, INPUT_PULLUP | MODE1 */
+					0x08 0x31	/* gpmc_ad2.mmc1_dat2, INPUT_PULLUP | MODE1 */
+					0x0c 0x31	/* gpmc_ad3.mmc1_dat3, INPUT_PULLUP | MODE1 */
+					0x10 0x31	/* gpmc_ad4.mmc1_dat4, INPUT_PULLUP | MODE1 */
+					0x14 0x31	/* gpmc_ad5.mmc1_dat5, INPUT_PULLUP | MODE1 */
+					0x18 0x31	/* gpmc_ad6.mmc1_dat6, INPUT_PULLUP | MODE1 */
+					0x1c 0x31	/* gpmc_ad7.mmc1_dat7, INPUT_PULLUP | MODE1 */
+				>;
+			};
+		};
+	};
+	fragment@1 {
+		target = <&mmc2>;
+		__overlay__ {
+			pinctrl-names = "default";
+			pinctrl-0 = <&emmc2_pins>;	/* wrong numbering */
+			vmmc-supply = <&ldo3_reg>;
+			bus-width = <8>;
+			ti,non-removable;
+			status = "okay";
+			ti,vcc-aux-disable-is-sleep;
+
+			reset = <&rstctl 0 0>;
+			reset-names = "eMMC_RSTn";
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-adafruit-lcd-00A0.dts b/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
new file mode 100644
index 0000000..8422bb5
--- /dev/null
+++ b/firmware/capes/cape-bone-adafruit-lcd-00A0.dts
@@ -0,0 +1,141 @@
+/*
+* Copyright (C) 2013 Matt Ranostay <mranostay@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.
+*/
+/dts-v1/;
+/plugin/;
+
+/*
+ * Pin assignments
+ *
+ * Module      Connector
+ * LITE    <-  P8.19
+ * MISO    ->  P9.29
+ * SCK     <-  P9.31
+ * MOSI    <-  P9.30
+ * TFT_CS  <-  P9.28
+ * CARD_CS <-  NC
+ * D/C     <-  P9.25
+ * RESET   <-  P9.27
+ *
+ */
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+	part-number = "BB-BONE-TFT-01";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.19",	/* bl: ehrpwm2A */
+		"P9.27",	/* lcd: gpio3_19 */
+		"P9.25",	/* lcd: gpio3_21 */
+		"P9.31",	/* spi: spi1_sclk */
+		"P9.29",	/* spi: spi1_d0 */
+		"P9.30",	/* spi: spi1_d1 */
+		"P9.28",	/* spi: spi1_cs0 */
+		/* the hardware IP uses */
+		"gpio3_19",
+		"gpio3_21",
+		"ehrpwm2A",
+		"spi1";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_backlight_pins: pinmux_pwm_backlight_pins {
+				pinctrl-single,pins = <
+					0x020  0x4      /* gpmc_ad8.gpio0_22 | MODE4 */
+				>;
+			};
+
+			bone_adafruit_lcd_pins: pinmux_bone_adafruit_lcd_pins {
+				pinctrl-single,pins = <
+					0x1a4 0x17      /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
+					0x1ac 0x17      /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
+				>;
+			};
+
+			bone_adafruit_spi1_pins: pinmux_adafruit_spi1_pins {
+				pinctrl-single,pins = <
+					0x190 0x33	/* mcasp0_aclkx.spi1_sclk, INPUT_PULLUP | MODE3 */
+					0x194 0x33	/* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
+					0x198 0x13	/* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
+					0x19c 0x13	/* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&epwmss2>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@2 {
+		target = <&ehrpwm2>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+
+	fragment@3 {
+		target = <&spi1>;
+
+		__overlay__ {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			status		= "okay";
+			pinctrl-names	= "default";
+			pinctrl-0	= <&bone_adafruit_spi1_pins>;
+
+			lcd@0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";
+				reg = <0>;
+
+				spi-max-frequency = <8000000>;
+				spi-cpol;
+				spi-cpha;
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_adafruit_lcd_pins>;
+
+				st7735-rst = <&gpio4 19 0>;
+				st7735-dc = <&gpio4 21 0>;
+			};
+		};
+	};
+
+	fragment@4 {
+		target = <&ocp>;
+
+		/* avoid stupid warning */
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		__overlay__ {
+			adafruit-tft-backlight {
+				compatible	= "pwm-backlight";
+				pinctrl-names	= "default";
+				pinctrl-0	= <&pwm_backlight_pins>;
+
+				pwms = <&ehrpwm2 0 500000 0>;
+
+				pwm-names = "st7735fb";
+				brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+				default-brightness-level = <101>; /* index to the array above */
+			};
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-adafruit-rtc-00A0.dts b/firmware/capes/cape-bone-adafruit-rtc-00A0.dts
new file mode 100644
index 0000000..35344fd
--- /dev/null
+++ b/firmware/capes/cape-bone-adafruit-rtc-00A0.dts
@@ -0,0 +1,57 @@
+/*
+* Copyright (C) 2013 Matt Ranostay <mranostay@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.
+*/
+/dts-v1/;
+/plugin/;
+
+/*
+ * Pin assignments
+ *
+ * Module     Connector
+ * SCL     -> P9.19
+ * SDA     <- P9.20
+ * SQW     <- NC
+ *
+ */
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+	part-number = "BB-BONE-RTC-01";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.19",	/* bl: ehrpwm2A */
+		"P9.27",	/* lcd: gpio3_19 */
+		"P9.25",	/* lcd: gpio3_21 */
+		"P9.31",	/* spi: spi1_sclk */
+		"P9.29",	/* spi: spi1_d0 */
+		"P9.30",	/* spi: spi1_d1 */
+		"P9.28",	/* spi: spi1_cs0 */
+		/* the hardware IP uses */
+		"gpio3_19",
+		"gpio3_21",
+		"ehrpwm2A",
+		"spi1";
+
+	fragment@0 {
+		target = <&i2c2>;
+
+		__overlay__ {
+			/* shut up DTC warnings */
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* DS1307 RTC module */
+			rtc@68 {
+				compatible = "dallas,ds1307";
+				reg = <0x68>;
+			};
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-dvi-00A0.dts b/firmware/capes/cape-bone-dvi-00A0.dts
new file mode 100644
index 0000000..577a474
--- /dev/null
+++ b/firmware/capes/cape-bone-dvi-00A0.dts
@@ -0,0 +1,137 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-DVID-01";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.14",	/* led: gpio1_18 */
+		"P9.16",	/* led: gpio1_19 */
+		"P8.4",		/* lcd: gpio1_7 */
+		"P8.45",	/* lcd: lcd_data0 */
+		"P8.46",	/* lcd: lcd_data1 */
+		"P8.43",	/* lcd: lcd_data2 */
+		"P8.44",	/* lcd: lcd_data3 */
+		"P8.41",	/* lcd: lcd_data4 */
+		"P8.42",	/* lcd: lcd_data5 */
+		"P8.39",	/* lcd: lcd_data6 */
+		"P8.40",	/* lcd: lcd_data7 */
+		"P8.37",	/* lcd: lcd_data8 */
+		"P8.38",	/* lcd: lcd_data9 */
+		"P8.36",	/* lcd: lcd_data10 */
+		"P8.34",	/* lcd: lcd_data11 */
+		"P8.35",	/* lcd: lcd_data12 */
+		"P8.33",	/* lcd: lcd_data13 */
+		"P8.31",	/* lcd: lcd_data14 */
+		"P8.32",	/* lcd: lcd_data15 */
+		"P8.27",	/* lcd: lcd_vsync */
+		"P8.29",	/* lcd: lcd_hsync */
+		"P8.28",	/* lcd: lcd_pclk */
+		"P8.30",	/* lcd: lcd_ac_bias_en */
+		/* the hardware IP uses */
+		"gpio1_18",
+		"gpio1_19",
+		"gpio1_7",
+		"lcd";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_dvi_cape_led_pins: pinmux_bone_dvi_cape_led_pins {
+				pinctrl-single,pins = <
+					0x48 0x07	/* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
+					0x4c 0x07	/* gpmc_a3.gpio1_19, OUTPUT | MODE7 */
+				>;
+			};
+
+			bone_dvi_cape_dvi_00A0_pins: pinmux_bone_dvi_cape_dvi_00A0_pins {
+				pinctrl-single,pins = <
+					0x1c 0x07	/* gpmc_ad7.gpio1_7, OUTPUT | MODE7 - DVIPDn */
+
+					0xa0 0x08	/* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa4 0x08	/* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa8 0x08	/* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xac 0x08	/* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb0 0x08	/* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb4 0x08	/* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb8 0x08	/* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xbc 0x08	/* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc0 0x08	/* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc4 0x08	/* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc8 0x08	/* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xcc 0x08	/* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd0 0x08	/* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd4 0x08	/* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd8 0x08	/* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xdc 0x08	/* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xe0 0x00	/* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe4 0x00	/* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe8 0x00	/* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xec 0x00	/* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			gpio-leds-cape-dvi {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_dvi_cape_led_pins>;
+
+				dvi-led0 {
+					label = "dvi:green:usr0";
+					gpios = <&gpio2 18 0>;
+					linux,default-trigger = "heartbeat";
+					default-state = "off";
+				};
+
+				dvi-led1 {
+					label = "dvi:green:usr1";
+					gpios = <&gpio2 19 0>;
+					linux,default-trigger = "mmc0";
+					default-state = "off";
+				};
+			};
+
+			/* use the DVI panel now */
+			panel {
+				compatible = "tilcdc,tfp410";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_dvi_cape_dvi_00A0_pins>;
+				ti,power-gpio = <&gpio1 7 0x0>;
+				i2c = <&i2c2>;
+			};
+
+			fb {
+				compatible = "ti,am33xx-tilcdc";
+				reg = <0x4830e000 0x1000>;
+				interrupt-parent = <&intc>;
+				interrupts = <36>;
+				ti,hwmods = "lcdc";
+			};
+
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-dvi-00A1.dts b/firmware/capes/cape-bone-dvi-00A1.dts
new file mode 100644
index 0000000..ac8b4c5
--- /dev/null
+++ b/firmware/capes/cape-bone-dvi-00A1.dts
@@ -0,0 +1,207 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-DVID-01";
+	version = "00A1", "A1";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.14",	/* led: gpio1_18 */
+		"P9.16",	/* led: gpio1_19 */
+		"P9.25",	/* mcasp0: mcasp0_ahclkx */
+		"P9.28",	/* mcasp0: mcasp0_axr2 */
+		"P9.29",	/* mcasp0: mcasp0_fsx */
+		"P9.31",	/* mcasp0: mcasp0_aclkx */
+		"P8.4",		/* lcd: gpio1_7 */
+		"P8.45",	/* lcd: lcd_data0 */
+		"P8.46",	/* lcd: lcd_data1 */
+		"P8.43",	/* lcd: lcd_data2 */
+		"P8.44",	/* lcd: lcd_data3 */
+		"P8.41",	/* lcd: lcd_data4 */
+		"P8.42",	/* lcd: lcd_data5 */
+		"P8.39",	/* lcd: lcd_data6 */
+		"P8.40",	/* lcd: lcd_data7 */
+		"P8.37",	/* lcd: lcd_data8 */
+		"P8.38",	/* lcd: lcd_data9 */
+		"P8.36",	/* lcd: lcd_data10 */
+		"P8.34",	/* lcd: lcd_data11 */
+		"P8.35",	/* lcd: lcd_data12 */
+		"P8.33",	/* lcd: lcd_data13 */
+		"P8.31",	/* lcd: lcd_data14 */
+		"P8.32",	/* lcd: lcd_data15 */
+		"P8.27",	/* lcd: lcd_vsync */
+		"P8.29",	/* lcd: lcd_hsync */
+		"P8.28",	/* lcd: lcd_pclk */
+		"P8.30",	/* lcd: lcd_ac_bias_en */
+		/* the hardware IP uses */
+		"gpio1_18",
+		"gpio1_19",
+		"gpio1_7",
+		"mcasp0",
+		"lcd";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_dvi_cape_led_pins: pinmux_bone_dvi_cape_led_pins {
+				pinctrl-single,pins = <
+					0x48 0x07	/* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
+					0x4c 0x07	/* gpmc_a3.gpio1_19, OUTPUT | MODE7 */
+				>;
+			};
+
+			bone_dvi_cape_dvi_00A1_pins: pinmux_bone_dvi_cape_dvi_00A1_pins {
+				pinctrl-single,pins = <
+					0x1c 0x07	/* gpmc_ad7.gpio1_7, OUTPUT | MODE7 - DVIPDn */
+
+					0xa0 0x08	/* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa4 0x08	/* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa8 0x08	/* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xac 0x08	/* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb0 0x08	/* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb4 0x08	/* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb8 0x08	/* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xbc 0x08	/* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc0 0x08	/* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc4 0x08	/* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc8 0x08	/* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xcc 0x08	/* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd0 0x08	/* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd4 0x08	/* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd8 0x08	/* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xdc 0x08	/* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xe0 0x00	/* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe4 0x00	/* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe8 0x00	/* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xec 0x00	/* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+
+			bone_dvi_cape_audio_pins: pinmux_bone_dvi_cape_audio_pins {
+				pinctrl-single,pins = <
+					0x190 0x20	/* mcasp0_aclkx.mcasp0_aclkx, INPUT | MODE0 */
+					0x194 0x20	/* mcasp0_fsx.mcasp0_fsx, INPUT | MODE0 */
+					0x19c 0x22	/* mcasp0_ahclkr.mcasp0_axr2, INPUT | MODE2 */
+					0x1ac 0x22	/* mcasp0_ahclkx.mcasp0_axr3, INPUT | MODE2 */
+
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			gpio-leds-cape-dvi {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_dvi_cape_led_pins>;
+
+				dvi-led0 {
+					label = "dvi:green:usr0";
+					gpios = <&gpio2 18 0>;
+					linux,default-trigger = "heartbeat";
+					default-state = "off";
+				};
+
+				dvi-led1 {
+					label = "dvi:green:usr1";
+					gpios = <&gpio2 19 0>;
+					linux,default-trigger = "mmc0";
+					default-state = "off";
+				};
+			};
+
+			/* use the DVI panel now */
+			panel {
+				compatible = "tilcdc,tfp410";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
+				ti,power-gpio = <&gpio1 7 0x0>;
+				i2c = <&i2c2>;
+			};
+
+			fb {
+				compatible = "ti,am33xx-tilcdc";
+				reg = <0x4830e000 0x1000>;
+				interrupt-parent = <&intc>;
+				interrupts = <36>;
+				ti,hwmods = "lcdc";
+			};
+
+		};
+	};
+
+	fragment@2 {
+		target = <&i2c2>;
+		__overlay__ {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			tlv320aic3x: tlv320aic3x@1b {
+				compatible = "ti,tlv320aic3x";
+				reg = <0x1b>;
+				status = "okay";
+			};
+		};
+	};
+
+	fragment@3 {
+		target = <&mcasp0>;
+		__overlay__ {
+			pinctrl-names = "default";
+			pinctrl-0 = <&bone_dvi_cape_audio_pins>;
+
+			status = "okay";
+
+			op-mode = <0>;          /* MCASP_IIS_MODE */
+			tdm-slots = <2>;
+			num-serializer = <16>;
+			serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+				0 0 2 1
+				0 0 0 0
+				0 0 0 0
+				0 0 0 0
+			>;
+			tx-num-evt = <1>;
+			rx-num-evt = <1>;
+		};
+	};
+
+	fragment@4 {
+		target = <&ocp>;
+		__overlay__ {
+			sound {
+				compatible = "ti,da830-evm-audio";
+				ti,model = "DA830 EVM";
+				ti,audio-codec = <&tlv320aic3x>;
+				ti,mcasp-controller = <&mcasp0>;
+				ti,codec-clock-rate = <12000000>;
+				ti,audio-routing =
+					"Headphone Jack",       "HPLOUT",
+					"Headphone Jack",       "HPROUT",
+					"LINE1L",               "Line In",
+					"LINE1R",               "Line In";
+			};
+		};
+
+	};
+};
diff --git a/firmware/capes/cape-bone-dvi-00A2.dts b/firmware/capes/cape-bone-dvi-00A2.dts
new file mode 100644
index 0000000..4c54804
--- /dev/null
+++ b/firmware/capes/cape-bone-dvi-00A2.dts
@@ -0,0 +1,137 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-DVID-01";
+	version = "00A3", "00A2", "A2";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.14",	/* led: gpio1_18 */
+		"P9.16",	/* led: gpio1_19 */
+		"P8.4",		/* lcd: gpio1_7 */
+		"P8.45",	/* lcd: lcd_data0 */
+		"P8.46",	/* lcd: lcd_data1 */
+		"P8.43",	/* lcd: lcd_data2 */
+		"P8.44",	/* lcd: lcd_data3 */
+		"P8.41",	/* lcd: lcd_data4 */
+		"P8.42",	/* lcd: lcd_data5 */
+		"P8.39",	/* lcd: lcd_data6 */
+		"P8.40",	/* lcd: lcd_data7 */
+		"P8.37",	/* lcd: lcd_data8 */
+		"P8.38",	/* lcd: lcd_data9 */
+		"P8.36",	/* lcd: lcd_data10 */
+		"P8.34",	/* lcd: lcd_data11 */
+		"P8.35",	/* lcd: lcd_data12 */
+		"P8.33",	/* lcd: lcd_data13 */
+		"P8.31",	/* lcd: lcd_data14 */
+		"P8.32",	/* lcd: lcd_data15 */
+		"P8.27",	/* lcd: lcd_vsync */
+		"P8.29",	/* lcd: lcd_hsync */
+		"P8.28",	/* lcd: lcd_pclk */
+		"P8.30",	/* lcd: lcd_ac_bias_en */
+		/* the hardware IP uses */
+		"gpio1_18",
+		"gpio1_19",
+		"gpio1_7",
+		"lcd";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_dvi_cape_led_pins: pinmux_bone_dvi_cape_led_pins {
+				pinctrl-single,pins = <
+					0x48 0x07	/* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
+					0x4c 0x07	/* gpmc_a3.gpio1_19, OUTPUT | MODE7 */
+				>;
+			};
+
+			bone_dvi_cape_dvi_00A2_pins: pinmux_bone_dvi_cape_dvi_00A2_pins {
+				pinctrl-single,pins = <
+					0x1c 0x07	/* gpmc_ad7.gpio1_7, OUTPUT | MODE7 - DVIPDn */
+
+					0xa0 0x08	/* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa4 0x08	/* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa8 0x08	/* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xac 0x08	/* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb0 0x08	/* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb4 0x08	/* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb8 0x08	/* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xbc 0x08	/* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc0 0x08	/* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc4 0x08	/* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc8 0x08	/* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xcc 0x08	/* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd0 0x08	/* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd4 0x08	/* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd8 0x08	/* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xdc 0x08	/* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xe0 0x00	/* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe4 0x00	/* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe8 0x00	/* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xec 0x00	/* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			gpio-leds-cape-dvi {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_dvi_cape_led_pins>;
+
+				dvi-led0 {
+					label = "dvi:green:usr0";
+					gpios = <&gpio2 18 0>;
+					linux,default-trigger = "heartbeat";
+					default-state = "off";
+				};
+
+				dvi-led1 {
+					label = "dvi:green:usr1";
+					gpios = <&gpio2 19 0>;
+					linux,default-trigger = "mmc0";
+					default-state = "off";
+				};
+			};
+
+			/* use the DVI panel now */
+			panel {
+				compatible = "tilcdc,tfp410";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_dvi_cape_dvi_00A2_pins>;
+				ti,power-gpio = <&gpio1 31 0x0>;
+				i2c = <&i2c2>;
+			};
+
+			fb {
+				compatible = "ti,am33xx-tilcdc";
+				reg = <0x4830e000 0x1000>;
+				interrupt-parent = <&intc>;
+				interrupts = <36>;
+				ti,hwmods = "lcdc";
+			};
+
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-exptest-00A0.dts b/firmware/capes/cape-bone-exptest-00A0.dts
new file mode 100644
index 0000000..0d6618c
--- /dev/null
+++ b/firmware/capes/cape-bone-exptest-00A0.dts
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-EXPTEST";
+	version = "00A0";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			bone_exp_input_gpio_pins: pinmux_bone_exp_input_gpio_pins {
+				pinctrl-single,pins = <
+					/* P8 connector on the bone */
+					/* P3 - P46 pins, B_A3-B_A46, INPUT | PULLDIS | MODE7 */
+					// 0x018 0x2f /*  3 GPIO1_6    gpmc_ad6.gpio1[6]      */
+					// 0x01C 0x2f /*  4 GPIO1_7    gpmc_ad7.gpio1[7]      */
+					// 0x008 0x2f /*  5 GPIO1_2    gpmc_ad2.gpio1[2]      */
+					// 0x00C 0x2f /*  6 GPIO1_3    gpmc_ad3.gpio1[3]      */
+					0x090 0x2f /*  7 TIMER4     gpmc_advn_ale.gpio2[2] */
+					0x094 0x2f /*  8 TIMER7     gpmc_oen_ren.gpio2[3]  */
+					0x09C 0x2f /*  9 TIMER5     gpmc_ben0_cle.gpio2[5] */
+					0x098 0x2f /* 10 TIMER6     gpmc_wen.gpio2[4]      */
+					0x034 0x2f /* 11 GPIO1_13   gpmc_ad13.gpio1[13]    */
+					0x030 0x2f /* 12 GPIO1_12   gpmc_ad12.gpio1[12]    */
+					0x024 0x2f /* 13 EHRPWM2B   gpmc_ad9 .gpio0[23]    */
+					0x028 0x2f /* 14 GPIO0_26   gpmc_ad10.gpio0[26]    */
+					0x03C 0x2f /* 15 GPIO1_15   gpmc_ad15.gpio1[15]    */
+					0x038 0x2f /* 16 GPIO1_14   gpmc_ad14.gpio1[14]    */
+					0x02C 0x2f /* 17 GPIO0_27   gpmc_ad11.gpio0[27]    */
+					0x08C 0x2f /* 18 GPIO2_1    gpmc_clk .gpio2[1]     */
+					0x020 0x2f /* 19 EHRPWM2A   gpmc_ad8 .gpio0[22]    */
+					// 0x084 0x2f /* 20 GPIO1_31   gpmc_csn2.gpio1[31]    */
+					// 0x080 0x2f /* 21 GPIO1_30   gpmc_csn1.gpio1[30]    */
+					// 0x014 0x2f /* 22 GPIO1_5    gpmc_ad5 .gpio1[5]     */
+					// 0x010 0x2f /* 23 GPIO1_4    gpmc_ad4 .gpio1[4]     */
+					// 0x004 0x2f /* 24 GPIO1_1    gpmc_ad1 .gpio1[1]     */
+					// 0x000 0x2f /* 25 GPIO1_0    gpmc_ad0 .gpio1[0]     */
+					0x07C 0x2f /* 26 GPIO1_29   gpmc_csn0.gpio1[29]    */
+
+					/* P9 connector on the bone */
+					/* B_B0-B_B19, INPUT | PULLDIS | MODE7 */
+					0x070 0x2f /* 11 UART4_RXD  gpmc_wait0.gpio0[30]   */
+					0x078 0x2f /* 12 GPIO1_28   gpmc_be1n.gpio1[28]    */
+					0x074 0x2f /* 13 UART4_TXD  gpmc_wpn.gpio0[31]     */
+					0x048 0x2f /* 14 EHRPWM1A   gpmc_a2.gpio1[18]      */
+					0x040 0x2f /* 15 GPIO1_16   gpmc_a0.gpio1[16]      */
+					0x04C 0x2f /* 16 EHRPWM1B   gpmc_a3.gpio1[19]      */
+
+					0x154 0x2f /* 21 UART2_TXD  spi0_d0.gpio0[3]       */
+					0x150 0x2f /* 22 UART2_RXD  spi0_sclk.gpio0[2]     */
+					0x044 0x2f /* 23 GPIO1_17   gpmc_a1.gpio1[17]      */
+					0x1AC 0x2f /* 25 GPIO3_21   mcasp0_ahclkx.gpio3[21]*/
+					0x1A4 0x2f /* 27 GPIO3_19   mcasp0_fsr.gpio3[19]   */
+					0x19C 0x2f /* 28 SPI1_CS0   mcasp0_ahclkr.gpio3[17]*/
+					0x198 0x2f /* 30 SPI1_D1    mcasp0_axr0.gpio3[16]  */
+					0x190 0x2f /* 31 SPI1_SCLK  mcasp0_aclkx.gpio3[14] */
+					0x1B4 0x2f /* 41 CLKOUT2    xdma_event_intr1.gpio0[20]*/
+					0x164 0x2f /* 42 GPIO0_7    eCAP0_in_PWM0_out.gpio0[7]*/
+				>;
+			};
+
+			bone_exp_output_gpio_pins: pinmux_bone_exp_output_gpio_pins {
+				pinctrl-single,pins = <
+					/* P8 connector on the bone */
+					/* P3 - P46 pins, B_A3-B_A46, OUTPUT | MODE7 */
+					// 0x018 0x07 /*  3 GPIO1_6    gpmc_ad6.gpio1[6]      */
+					// 0x01C 0x07 /*  4 GPIO1_7    gpmc_ad7.gpio1[7]      */
+					// 0x008 0x07 /*  5 GPIO1_2    gpmc_ad2.gpio1[2]      */
+					// 0x00C 0x07 /*  6 GPIO1_3    gpmc_ad3.gpio1[3]      */
+					0x090 0x07 /*  7 TIMER4     gpmc_advn_ale.gpio2[2] */
+					0x094 0x07 /*  8 TIMER7     gpmc_oen_ren.gpio2[3]  */
+					0x09C 0x07 /*  9 TIMER5     gpmc_ben0_cle.gpio2[5] */
+					0x098 0x07 /* 10 TIMER6     gpmc_wen.gpio2[4]      */
+					0x034 0x07 /* 11 GPIO1_13   gpmc_ad13.gpio1[13]    */
+					0x030 0x07 /* 12 GPIO1_12   gpmc_ad12.gpio1[12]    */
+					0x024 0x07 /* 13 EHRPWM2B   gpmc_ad9 .gpio0[23]    */
+					0x028 0x07 /* 14 GPIO0_26   gpmc_ad10.gpio0[26]    */
+					0x03C 0x07 /* 15 GPIO1_15   gpmc_ad15.gpio1[15]    */
+					0x038 0x07 /* 16 GPIO1_14   gpmc_ad14.gpio1[14]    */
+					0x02C 0x07 /* 17 GPIO0_27   gpmc_ad11.gpio0[27]    */
+					0x08C 0x07 /* 18 GPIO2_1    gpmc_clk .gpio2[1]     */
+					0x020 0x07 /* 19 EHRPWM2A   gpmc_ad8 .gpio0[22]    */
+					// 0x084 0x07 /* 20 GPIO1_31   gpmc_csn2.gpio1[31]    */
+					// 0x080 0x07 /* 21 GPIO1_30   gpmc_csn1.gpio1[30]    */
+					// 0x014 0x07 /* 22 GPIO1_5    gpmc_ad5 .gpio1[5]     */
+					// 0x010 0x07 /* 23 GPIO1_4    gpmc_ad4 .gpio1[4]     */
+					// 0x004 0x07 /* 24 GPIO1_1    gpmc_ad1 .gpio1[1]     */
+					// 0x000 0x07 /* 25 GPIO1_0    gpmc_ad0 .gpio1[0]     */
+					0x07C 0x07 /* 26 GPIO1_29   gpmc_csn0.gpio1[29]    */
+
+					/* P9 connector on the bone */
+					/* B_B0-B_B19, INPUT | PULLDIS | MODE7 */
+					0x070 0x07 /* 11 UART4_RXD  gpmc_wait0.gpio0[30]   */
+					0x078 0x07 /* 12 GPIO1_28   gpmc_be1n.gpio1[28]    */
+					0x074 0x07 /* 13 UART4_TXD  gpmc_wpn.gpio0[31]     */
+					0x048 0x07 /* 14 EHRPWM1A   gpmc_a2.gpio1[18]      */
+					0x040 0x07 /* 15 GPIO1_16   gpmc_a0.gpio1[16]      */
+					0x04C 0x07 /* 16 EHRPWM1B   gpmc_a3.gpio1[19]      */
+
+					0x154 0x07 /* 21 UART2_TXD  spi0_d0.gpio0[3]       */
+					0x150 0x07 /* 22 UART2_RXD  spi0_sclk.gpio0[2]     */
+					0x044 0x07 /* 23 GPIO1_17   gpmc_a1.gpio1[17]      */
+					0x1AC 0x07 /* 25 GPIO3_21   mcasp0_ahclkx.gpio3[21]*/
+					0x1A4 0x07 /* 27 GPIO3_19   mcasp0_fsr.gpio3[19]   */
+					0x19C 0x07 /* 28 SPI1_CS0   mcasp0_ahclkr.gpio3[17]*/
+					0x198 0x07 /* 30 SPI1_D1    mcasp0_axr0.gpio3[16]  */
+					0x190 0x07 /* 31 SPI1_SCLK  mcasp0_aclkx.gpio3[14] */
+					0x1B4 0x07 /* 41 CLKOUT2    xdma_event_intr1.gpio0[20]*/
+					0x164 0x07 /* 42 GPIO0_7    eCAP0_in_PWM0_out.gpio0[7]*/
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			exp_test_pinmux_helper {
+				compatible = "bone-pinmux-helper";
+				status = "okay";
+
+				pinctrl-names = "input", "output";
+				pinctrl-0 = <&bone_exp_input_gpio_pins>;
+				pinctrl-1 = <&bone_exp_output_gpio_pins>;
+			};
+
+		};
+
+	};
+};
diff --git a/firmware/capes/cape-bone-geiger-00A0.dts b/firmware/capes/cape-bone-geiger-00A0.dts
new file mode 100644
index 0000000..fed2a63
--- /dev/null
+++ b/firmware/capes/cape-bone-geiger-00A0.dts
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-GEIGER";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.29",	/* led: gpio2_23 */
+		"P8.30",	/* led: gpio2_25 */
+		"P9.14",	/* geiger: ehrpwm1A */
+		"P9.28",	/* geiger: gpio3_17 */
+		"P9.36",	/* geiger: AIN5 */
+		/* the hardware IP uses */
+		"gpio2_23",
+		"gpio2_25",
+		"gpio3_17",
+		"ehrpwm1A",
+		"tscadc";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_geiger_cape_led_pins: pinmux_bone_geiger_cape_led_pins {
+				pinctrl-single,pins = <
+					0xe4 0x07	/* lcd_hsync.gpio2_23, OUTPUT | MODE7 */
+					0xec 0x07	/* lcd_ac_bias_en.gpio2_25, OUTPUT | MODE7 */
+				>;
+			};
+
+			bone_geiger_cape_pins: pinmux_bone_geiger_cape_pins {
+				pinctrl-single,pins = <
+					0x48 0x06       /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
+					/* 0x19c 0x34 */	/* mcasp0_ahclkr.eCAP2_in_PWM2_out, OMAP_MUX_MODE4 | INPUT_PULLUP */
+					0x19c 0x37 	/* mcasp0_ahclkr.gpio3_17, OMAP_MUX_MODE7 | INPUT_PULLUP */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&epwmss1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@2 {
+		target = <&ehrpwm1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@3 {
+		target = <&ocp>;
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			gpio-leds-cape-geiger {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_geiger_cape_led_pins>;
+
+				geiger-led0 {
+					label = "geiger:green:usr0";
+					gpios = <&gpio3 23 0>;
+					linux,default-trigger = "geiger-run";
+					default-state = "off";
+				};
+
+				geiger-led1 {
+					label = "geiger:red:usr1";
+					gpios = <&gpio3 25 0>;
+					linux,default-trigger = "geiger-event";
+					default-state = "off";
+				};
+
+			};
+
+			tscadc {
+				compatible = "ti,ti-tscadc";
+				reg = <0x44e0d000 0x1000>;
+
+				interrupt-parent = <&intc>;
+				interrupts = <16>;
+				ti,hwmods = "adc_tsc";
+				status = "okay";
+
+				adc {
+					ti,adc-channels = <0 1 2 3 4 5 6 7>;
+				};
+			};
+
+			bone-cape-geiger {
+				compatible = "bone-cape-geiger";
+				status = "okay";
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_geiger_cape_pins>;
+
+				pwms = <&ehrpwm1 0 500000 0>;
+				pwm-names = "bone-geiger-cape";
+
+				pwm-frequency  = <20000>;	/* 20KHz */
+				pwm-duty-cycle = <60>;		/* 60% */
+
+				event-blink-delay = <30>;	/* 30ms */
+
+				gpios = <&gpio4 17 0>;		/* pulse */
+
+				vsense-name = "AIN5";		/* analog vsense */
+				vsense-scale = <37325>;		/* scaling */
+			};
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-hexy-00A0.dts b/firmware/capes/cape-bone-hexy-00A0.dts
new file mode 100644
index 0000000..358f5e1
--- /dev/null
+++ b/firmware/capes/cape-bone-hexy-00A0.dts
@@ -0,0 +1,190 @@
+/*
+* Copyright (C) 2013 Matt Ranostay <mranostay@gmail.com>
+* Copyright (C) 2013 Koen Kooi <koen@circuitco.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/;
+/plugin/;
+
+/*
+ * Pin assignments
+ *
+ * Module      Connector
+ * LITE    <-  P8.19
+ * MISO    ->  P9.29
+ * SCK     <-  P9.31
+ * MOSI    <-  P9.30
+ * TFT_CS  <-  P9.28
+ * CARD_CS <-  NC
+ * D/C     <-  P9.25
+ * RESET   <-  P9.27
+ *
+ */
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+	part-number = "BB-BONE-HEXY-01";
+	version = "00A0";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pwm_backlight_pins: pinmux_pwm_backlight_pins {
+				pinctrl-single,pins = <
+					0x020  0x4      /* gpmc_ad8.gpio0_22 | MODE4 */
+				>;
+			};
+
+			bone_hexy_lcd_pins: pinmux_bone_hexy_lcd_pins {
+				pinctrl-single,pins = <
+					0x1a4 0x17      /* mcasp0_fsr.gpio3_19, OUTPUT_PULLUP | MODE7 */
+					0x1ac 0x17      /* mcasp0_ahclkx.gpio3_21, OUTPUT_PULLUP | MODE7 */
+				>;
+			};
+
+			bone_hexy_spi1_pins: pinmux_adafruit_spi1_pins {
+				pinctrl-single,pins = <
+					0x190 0x33	/* mcasp0_aclkx.spi1_sclk, INPUT_PULLUP | MODE3 */
+					0x194 0x33	/* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
+					0x198 0x13	/* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
+					0x19c 0x13	/* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&epwmss2>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@2 {
+		target = <&ehrpwm2>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+
+	fragment@3 {
+		target = <&spi1>;
+
+		__overlay__ {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			status		= "okay";
+			pinctrl-names	= "default";
+			pinctrl-0	= <&bone_hexy_spi1_pins>;
+
+			lcd@0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				compatible = "adafruit,tft-lcd-1.8-green", "sitronix,st7735";
+				reg = <0>;
+
+				spi-max-frequency = <16000000>;
+				spi-cpol;
+				spi-cpha;
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_hexy_lcd_pins>;
+
+				st7735-rst = <&gpio4 19 0>;
+				st7735-dc = <&gpio4 21 0>;
+			};
+		};
+	};
+
+	fragment@4 {
+		target = <&ocp>;
+
+		/* avoid stupid warning */
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		__overlay__ {
+			hexy_display {
+				compatible	= "pwm-backlight";
+				pinctrl-names	= "default";
+				pinctrl-0	= <&pwm_backlight_pins>;
+
+				pwms = <&ehrpwm2 0 500000 0>;
+
+				pwm-names = "st7735fb";
+				brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+				default-brightness-level = <101>; /* index to the array above */
+			};
+		};
+	};
+
+	fragment@5 {
+		target = <&i2c2>;
+
+		__overlay__ {
+			/* needed to avoid gripping by DTC */
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			lsm303dlhc_magn@1e {
+				compatible = "st,lsm303dlhc_magn";
+				reg = <0x1E>;
+			};
+
+			lsm303dlh_accel@1e {
+				compatible = "st,lsm303dlhc_accel";
+				reg = <0x19>;
+			};
+
+			vcnl4000@13 {
+				compatible = "vishay,vcnl4000";
+				reg = <0x13>;
+			};
+
+			ssd1306: oled@3c {
+				compatible = "solomon,ssd1306fb-i2c";
+				reg = <0x3c>;
+				reset-gpios = <&gpio2 17 0>;
+				solomon,height = <32>;
+				solomon,width = <128>;
+				solomon,page-offset = <0>;
+			};
+		};
+	};
+
+	fragment@6 {
+		target = <&ocp>;
+		__overlay__ {
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			tscadc {
+				compatible = "ti,ti-tscadc";
+				reg = <0x44e0d000 0x1000>;
+
+				interrupt-parent = <&intc>;
+				interrupts = <16>;
+				ti,hwmods = "adc_tsc";
+				status = "okay";
+
+				adc {
+					ti,adc-channels = <0 1 2 3 4 5 6 7>;
+				};
+			};
+
+			test_helper: helper {
+				compatible = "bone-iio-helper";
+				vsense-name  = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
+				vsense-scale = <100     100     100     100     100     100     100     100>;
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-iio-00A0.dts b/firmware/capes/cape-bone-iio-00A0.dts
new file mode 100644
index 0000000..416712b
--- /dev/null
+++ b/firmware/capes/cape-bone-iio-00A0.dts
@@ -0,0 +1,59 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "iio-test";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.39",	/* AIN0 */
+		"P9.40",	/* AIN1 */
+		"P9.37",	/* AIN2 */
+		"P9.38",	/* AIN3 */
+		"P9.33",	/* AIN4 */
+		"P9.36",	/* AIN5 */
+		"P9.35",	/* AIN6 */
+		/* the hardware IP uses */
+		"tscadc";
+
+	fragment@0 {
+		target = <&ocp>;
+		__overlay__ {
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			tscadc {
+				compatible = "ti,ti-tscadc";
+				reg = <0x44e0d000 0x1000>;
+
+				interrupt-parent = <&intc>;
+				interrupts = <16>;
+				ti,hwmods = "adc_tsc";
+				status = "okay";
+
+				adc {
+					ti,adc-channels = <0 1 2 3 4 5 6 7>;
+				};
+			};
+
+			test_helper: helper {
+				compatible = "bone-iio-helper";
+				vsense-name  = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
+				vsense-scale = <100     100     100     100     100     100     100     100>;
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-lcd3-00A0.dts b/firmware/capes/cape-bone-lcd3-00A0.dts
new file mode 100644
index 0000000..8628219
--- /dev/null
+++ b/firmware/capes/cape-bone-lcd3-00A0.dts
@@ -0,0 +1,271 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-LCD3-01";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.45",	/* lcd: lcd_data0 */
+		"P8.46",	/* lcd: lcd_data1 */
+		"P8.43",	/* lcd: lcd_data2 */
+		"P8.44",	/* lcd: lcd_data3 */
+		"P8.41",	/* lcd: lcd_data4 */
+		"P8.42",	/* lcd: lcd_data5 */
+		"P8.39",	/* lcd: lcd_data6 */
+		"P8.40",	/* lcd: lcd_data7 */
+		"P8.37",	/* lcd: lcd_data8 */
+		"P8.38",	/* lcd: lcd_data9 */
+		"P8.36",	/* lcd: lcd_data10 */
+		"P8.34",	/* lcd: lcd_data11 */
+		"P8.35",	/* lcd: lcd_data12 */
+		"P8.33",	/* lcd: lcd_data13 */
+		"P8.31",	/* lcd: lcd_data14 */
+		"P8.32",	/* lcd: lcd_data15 */
+		"P8.27",	/* lcd: lcd_vsync */
+		"P8.29",	/* lcd: lcd_hsync */
+		"P8.28",	/* lcd: lcd_pclk */
+		"P8.30",	/* lcd: lcd_ac_bias_en */
+		"P9.14",	/* led: gpio1_18 */
+		"P9.16",	/* led: gpio1_19 */
+		"P9.15",	/* keys: gpio1_16 */
+		"P9.23",	/* keys: gpio1_17 */
+		"P9.27",	/* keys: gpio3_19 */
+		"P9.12",	/* keys: gpio1_28 */
+		"P9.42",	/* keys: gpio0_7 */
+		/* the hardware IP uses */
+		"gpio1_18",
+		"gpio1_19",
+		"gpio1_16",
+		"gpio1_17",
+		"gpio3_19",
+		"gpio0_7",
+		"lcd",
+		"tps-bl",
+		"tscadc";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_lcd3_cape_led_00A0_pins: pinmux_bone_lcd3_cape_led_00A0_pins {
+				pinctrl-single,pins = <
+					0x48 0x07	/* gpmc_a2.gpio1_18, OUTPUT | MODE7 */
+					0x4c 0x07	/* gpmc_a3.gpio1_19, OUTPUT | MODE7 */
+				>;
+			};
+
+			bone_lcd3_cape_lcd_pins: pinmux_bone_lcd3_cape_lcd_pins {
+				pinctrl-single,pins = <
+					0xa0 0x08	/* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa4 0x08	/* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa8 0x08	/* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xac 0x08	/* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb0 0x08	/* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb4 0x08	/* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb8 0x08	/* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xbc 0x08	/* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc0 0x08	/* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc4 0x08	/* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc8 0x08	/* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xcc 0x08	/* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd0 0x08	/* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd4 0x08	/* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd8 0x08	/* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xdc 0x08	/* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xe0 0x00	/* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe4 0x00	/* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe8 0x00	/* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					// 0xec 0x00	/* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xec 0x07	/* lcd_ac_bias_en.gpio2_25 OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+
+			bone_lcd3_cape_keys_00A0_pins: pinmux_bone_lcd3_cape_keys_00A0_pins {
+				pinctrl-single,pins = <
+					0x040 0x2f	/* gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
+					0x044 0x2f	/* gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
+					0x1a4 0x2f	/* mcasp0_fsr.gpio3_19, INPUT | PULLDIS | MODE7 */
+					0x078 0x2f	/* gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
+					0x164 0x2f	/* ecap0_in_pwm0_out.gpio0_7, INPUT | PULLDIS | MODE7 */
+				>;
+			};
+
+		};
+	};
+
+	fragment@1 {
+		target = <&tps>;
+		__overlay__ {
+			backlight {
+				compatible = "tps65217-backlight";
+				isel = <1>;
+				fdim = <200>;
+				brightness = <100>;
+				tps = <&tps>;
+			};
+		};
+	};
+
+	fragment@2 {
+		target = <&ocp>;
+
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			tscadc {
+				compatible = "ti,ti-tscadc";
+				reg = <0x44e0d000 0x1000>;
+
+				interrupt-parent = <&intc>;
+				interrupts = <16>;
+				ti,hwmods = "adc_tsc";
+				status = "okay";
+
+				tsc {
+					ti,wires = <4>;
+					ti,x-plate-resistance = <200>;
+					ti,coordinate-readouts = <5>;
+					ti,wire-config = <0x00 0x11 0x22 0x33>;
+				};
+
+				adc {
+					ti,adc-channels = <4 5 6 7>;
+				};
+			};
+
+			gpio-leds-cape-lcd3 {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+
+				pinctrl-0 = <&bone_lcd3_cape_led_00A0_pins>;
+
+				lcd3-led0 {
+					label = "lcd3:green:usr0";
+					gpios = <&gpio2 18 0>;
+					linux,default-trigger = "heartbeat";
+					default-state = "off";
+				};
+
+				lcd3-led1 {
+					label = "lcd3:green:usr1";
+					gpios = <&gpio2 19 0>;
+					linux,default-trigger = "cpu0";
+					default-state = "off";
+				};
+			};
+
+			gpio_keys {
+				compatible = "gpio-keys";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd3_cape_keys_00A0_pins>;
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				button@1 {
+					debounce_interval = <50>;
+					linux,code = <105>;
+					label = "left";
+					gpios = <&gpio2 16 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@2 {
+					debounce_interval = <50>;
+					linux,code = <106>;
+					label = "right";
+					gpios = <&gpio2 17 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@3 {
+					debounce_interval = <50>;
+					linux,code = <103>;
+					label = "up";
+					gpios = <&gpio4 19 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@4 {
+					debounce_interval = <50>;
+					linux,code = <108>;
+					label = "down";
+					gpios = <&gpio2 28 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@5 {
+					debounce_interval = <50>;
+					linux,code = <28>;
+					label = "enter";
+					gpios = <&gpio1 7 0x1>;
+					gpio-key,wakeup;
+				};
+			};
+
+			/* Settings for CDTech_S035Q01 / LCD3 cape: */
+			panel {
+				compatible = "tilcdc,panel";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
+				panel-info {
+					ac-bias           = <255>;
+					ac-bias-intrpt    = <0>;
+					dma-burst-sz      = <16>;
+					bpp               = <16>;
+					fdd               = <0x80>;
+					tft-alt-mode      = <0>;
+					stn-565-mode      = <0>;
+					mono-8bit-mode    = <0>;
+					sync-edge         = <0>;
+					sync-ctrl         = <1>;
+					raster-order      = <0>;
+					fifo-th           = <0>;
+					invert-pxl-clk;
+				};
+				display-timings {
+					native-mode = <&timing0>;
+					timing0: 320x240 {
+						hactive         = <320>;
+						vactive         = <240>;
+						hback-porch     = <22>;
+						hfront-porch    = <59>;
+						hsync-len       = <48>;
+						vback-porch     = <12>;
+						vfront-porch    = <23>;
+						vsync-len       = <2>;
+						clock-frequency = <8000000>;
+						hsync-active    = <0>;
+						vsync-active    = <0>;
+					};
+				};
+			};
+
+			fb {
+				compatible = "ti,am33xx-tilcdc";
+				reg = <0x4830e000 0x1000>;
+				interrupt-parent = <&intc>;
+				interrupts = <36>;
+				ti,hwmods = "lcdc";
+				ti,power-gpio = <&gpio3 25 0>;
+			};
+
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-lcd3-00A2.dts b/firmware/capes/cape-bone-lcd3-00A2.dts
new file mode 100644
index 0000000..f285196
--- /dev/null
+++ b/firmware/capes/cape-bone-lcd3-00A2.dts
@@ -0,0 +1,281 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-LCD3-01";
+	version = "00A2";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.45",	/* lcd: lcd_data0 */
+		"P8.46",	/* lcd: lcd_data1 */
+		"P8.43",	/* lcd: lcd_data2 */
+		"P8.44",	/* lcd: lcd_data3 */
+		"P8.41",	/* lcd: lcd_data4 */
+		"P8.42",	/* lcd: lcd_data5 */
+		"P8.39",	/* lcd: lcd_data6 */
+		"P8.40",	/* lcd: lcd_data7 */
+		"P8.37",	/* lcd: lcd_data8 */
+		"P8.38",	/* lcd: lcd_data9 */
+		"P8.36",	/* lcd: lcd_data10 */
+		"P8.34",	/* lcd: lcd_data11 */
+		"P8.35",	/* lcd: lcd_data12 */
+		"P8.33",	/* lcd: lcd_data13 */
+		"P8.31",	/* lcd: lcd_data14 */
+		"P8.32",	/* lcd: lcd_data15 */
+		"P8.27",	/* lcd: lcd_vsync */
+		"P8.29",	/* lcd: lcd_hsync */
+		"P8.28",	/* lcd: lcd_pclk */
+		"P8.30",	/* lcd: lcd_ac_bias_en */
+		"P9.27",	/* led: gpio3_19 */
+		"P9.14",	/* bl: ehrpwm1a*/
+		"P9.15",	/* keys: gpio1_16*/
+		"P9.23",	/* keys: gpio1_17*/
+		"P9.16",	/* keys: gpio1_19*/
+		"P9.21",	/* keys: gpio0_3*/
+		/* the hardware IP uses */
+		"gpio3_19",
+		"gpio1_16",
+		"gpio1_17",
+		"gpio1_19",
+		"gpio0_3",
+		"lcd",
+		"ehrpwm1a",
+		"tscadc";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_lcd3_cape_led_00A2_pins: pinmux_bone_lcd3_cape_led_00A2_pins {
+				pinctrl-single,pins = <
+					0x1a4 0x07	/* mcasp0_fsr.gpio3_19, OUTPUT | MODE7 */
+				>;
+			};
+
+			pwm_bl_pins: pinmux_pwm_bl_pins {
+				pinctrl-single,pins = <
+					0x48 0x06       /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+
+			bone_lcd3_cape_lcd_pins: pinmux_bone_lcd3_cape_lcd_pins {
+				pinctrl-single,pins = <
+					0xa0 0x08	/* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa4 0x08	/* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa8 0x08	/* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xac 0x08	/* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb0 0x08	/* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb4 0x08	/* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb8 0x08	/* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xbc 0x08	/* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc0 0x08	/* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc4 0x08	/* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc8 0x08	/* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xcc 0x08	/* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd0 0x08	/* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd4 0x08	/* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd8 0x08	/* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xdc 0x08	/* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xe0 0x00	/* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe4 0x00	/* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe8 0x00	/* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					// 0xec 0x00    /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xec 0x07       /* lcd_ac_bias_en.gpio2_25 OMAP_MUX_MODE7 | AM33XX_PIN_OUTPUT */
+
+				>;
+			};
+
+			bone_lcd3_cape_keys_00A2_pins: pinmux_bone_lcd3_cape_keys_00A2_pins {
+				pinctrl-single,pins = <
+					0x040 0x2f	/* gpmc_a0.gpio1_16, INPUT | PULLDIS | MODE7 */
+					0x044 0x2f	/* gpmc_a1.gpio1_17, INPUT | PULLDIS | MODE7 */
+					0x04c 0x2f 	/* gpmc_a3.gpio1_19, INPUT | PULLDIS | MODE7 */
+					0x154 0x2f	/* P9_21 spi0_d0.gpio0_3 INPUT | PULLDIS | MODE7 */
+				>;
+			};
+
+		};
+	};
+
+	fragment@1 {
+		target = <&epwmss1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@2 {
+		target = <&ehrpwm1>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@3 {
+		target = <&ocp>;
+
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			backlight {
+				compatible      = "pwm-backlight";
+ 				pinctrl-names   = "default";
+				pinctrl-0       = <&pwm_bl_pins>;
+
+				pwms = <&ehrpwm1 0 500000 0>;
+				pwm-names = "LCD3";
+				brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+				default-brightness-level = <101>; /* index to the array above */
+				status = "okay";
+ 			};
+
+			tscadc {
+				compatible = "ti,ti-tscadc";
+				reg = <0x44e0d000 0x1000>;
+
+				interrupt-parent = <&intc>;
+				interrupts = <16>;
+				ti,hwmods = "adc_tsc";
+				status = "okay";
+
+				tsc {
+					ti,wires = <4>;
+					ti,x-plate-resistance = <200>;
+					ti,coordinate-readouts = <5>;
+					ti,wire-config = <0x00 0x11 0x22 0x33>;
+				};
+
+				adc {
+					ti,adc-channels = <4 5 6 7>;
+				};
+			};
+
+			gpio-leds-cape-lcd3 {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+
+				pinctrl-0 = <&bone_lcd3_cape_led_00A2_pins>;
+
+				lcd3-led0 {
+					label = "lcd3:green:usr0";
+					gpios = <&gpio4 19 0>;
+					linux,default-trigger = "heartbeat";
+					default-state = "off";
+				};
+
+			};
+
+			gpio_keys {
+				compatible = "gpio-keys";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd3_cape_keys_00A2_pins>;
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				button@1 {
+					debounce_interval = <50>;
+					linux,code = <105>;
+					label = "left";
+					gpios = <&gpio2 16 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@2 {
+					debounce_interval = <50>;
+					linux,code = <106>;
+					label = "right";
+					gpios = <&gpio2 17 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@3 {
+					debounce_interval = <50>;
+					linux,code = <103>;
+					label = "up";
+					gpios = <&gpio2 19 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@4 {
+					debounce_interval = <50>;
+					linux,code = <108>;
+					label = "down";
+					gpios = <&gpio4 16 0x1>;
+					gpio-key,wakeup;
+					autorepeat;
+				};
+				button@5 {
+					debounce_interval = <50>;
+					linux,code = <28>;
+					label = "enter";
+					gpios = <&gpio1 3 0x1>;
+					gpio-key,wakeup;
+				};
+			};
+
+			/* Settings for CDTech_S035Q01 / LCD3 cape: */
+			panel {
+				compatible = "tilcdc,panel";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
+				panel-info {
+					ac-bias           = <255>;
+					ac-bias-intrpt    = <0>;
+					dma-burst-sz      = <16>;
+					bpp               = <16>;
+					fdd               = <0x80>;
+					tft-alt-mode      = <0>;
+					stn-565-mode      = <0>;
+					mono-8bit-mode    = <0>;
+					sync-edge         = <0>;
+					sync-ctrl         = <1>;
+					raster-order      = <0>;
+					fifo-th           = <0>;
+					invert-pxl-clk;
+				};
+				display-timings {
+					native-mode = <&timing0>;
+					timing0: 320x240 {
+						hactive         = <320>;
+						vactive         = <240>;
+						hback-porch     = <22>;
+						hfront-porch    = <59>;
+						hsync-len       = <48>;
+						vback-porch     = <12>;
+						vfront-porch    = <23>;
+						vsync-len       = <2>;
+						clock-frequency = <8000000>;
+						hsync-active    = <0>;
+						vsync-active    = <0>;
+					};
+				};
+			};
+
+			fb {
+				compatible = "ti,am33xx-tilcdc";
+				reg = <0x4830e000 0x1000>;
+				interrupt-parent = <&intc>;
+				interrupts = <36>;
+				ti,hwmods = "lcdc";
+				ti,power-gpio = <&gpio3 25 0>;
+			};
+
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-mrf24j40-00A0.dts b/firmware/capes/cape-bone-mrf24j40-00A0.dts
new file mode 100644
index 0000000..7e7b6b8
--- /dev/null
+++ b/firmware/capes/cape-bone-mrf24j40-00A0.dts
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2013 Alan Ott <alan@signal11.us>
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti-beaglebone-black";
+
+	/* Identification */
+	part-number = "BB-BONE-MRF24J40";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.11",	/* gpio1_13 */
+		"P8.16",	/* gpio1_14 */
+		"P8.26",	/* gpio1_29 */
+		"P9.31",	/* spi1_sclk */
+		"P9.29",	/* spi1_d0 */
+		"P9.30",	/* spi1_d1 */
+		"P9.28",	/* spi1_cs0 */
+		/* the hardware IP uses */
+		"gpio1_13",
+		"gpio1_14",
+		"gpio1_29",
+		"spi1";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			mrf24j40_cape_pins: pinmux_mrf24j40_cape_pins {
+				pinctrl-single,pins = <
+					/* Pinmux comes from TRM section
+					   9.3.1: CONTROL_MODULE Regusters. */
+
+					/* so use GPIO1_13 (rst), GPIO1_14 (wake), then SPI1_CS0 (CS), and GPIO1_29 (INT) */
+					0x34 0x37 /* gpmc_ad13.gpio1_13 input, pull up, mode 7 */
+					0x38 0x2f /* gpmc_ad14.gpio1_14 input, no pull, mode 7 */
+					0x7c 0x2f /* gpmc_csn0.gpio1_29 input, no pull, mode 7 */
+				>;
+			};
+			bone_mrf24j40_spi1_pins: pinmux_bone_mrf24j40_spi1_pins {
+				pinctrl-single,pins = <
+					0x190 0x33	/* mcasp0_aclkx.spi1_sclk, RX_ENABLED | PULLUP | MODE3 */
+	 				0x194 0x33	/* mcasp0_fsx.spi1_d0, RX_ENABLED | PULLUP | MODE3 */
+					0x198 0x33	/* mcasp0_axr0.spi1_d1, RX_ENABLED | PULLUP | MODE3 */
+					0x19c 0x33	/* mcasp0_ahclkr.spi1_cs0, RX_ENABLED | PULLUP | MODE3 */
+				>;
+			};
+		};
+	};
+
+
+	fragment@1 {
+		target = <&spi1>;
+
+		__overlay__ {
+			/* needed to avoid DTC warnings */
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			status = "okay";
+			pinctrl-names = "default";
+			pinctrl-0 = <&bone_mrf24j40_spi1_pins>;
+
+			mrf24j40@0 {
+				compatible = "mrf24j40ma";
+				reg = <0>; /* CHIPSEL */
+				spi-max-frequency = <20000000>;
+				mode = <0>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&mrf24j40_cape_pins>;
+
+				interrupt-parent = <&gpio2>;
+				interrupts = <29>;
+
+				//mrf24j40-wake = <&gpio4 19>;
+				//mrf24j40-reset = <gpio21 0>;
+			};
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-nixie-00A0.dts b/firmware/capes/cape-bone-nixie-00A0.dts
new file mode 100644
index 0000000..e4ff3ab
--- /dev/null
+++ b/firmware/capes/cape-bone-nixie-00A0.dts
@@ -0,0 +1,121 @@
+/*
+* Copyright (C) 2013 Matt Ranostay <mranostay@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.
+*/
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "BB-BONE-NIXIE";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.25",	/* gpio3_21 */
+		"P8.45",	/* ehrpwm2A */
+		"P8.46",	/* ehrpwm2B */
+		"P9.31",	/* pr1_pru0_pru_r30_0 */
+		"P9.29",	/* pr1_pru0_pru_r30_1 */
+		"P9.27",	/* pr1_pru0_pru_r30_5 */
+		/* the hardware IP uses */
+		"gpio3_21",
+		"ehrpwm2A", "ehrpwm2B",
+		"pru";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+
+			bone_nixie_cape_led_pins: pinmux_bone_nixie_cape_led_pins {
+				pinctrl-single,pins = <
+					0x1ac 0x07	/* mcasp0_ahclkx.gpio3_21, MODE7 */
+				>;
+			};
+
+			bone_nixie_cape_pins: pinmux_bone_nixie_cape_pins {
+				pinctrl-single,pins = <
+					0x0a0 0x03      /* lcd_data0.gpio2_6 | MODE3 */
+					0x0a4 0x03      /* lcd_data1.gpio2_7 | MODE3 */
+				>;
+		        };
+
+			pruss_pins: pinmux_pruss_pins {
+				pinctrl-single,pins = <
+					0x190 0x05	/* mcasp0_aclkx.pr1_pru0_pru_r30_0, MODE5 | DATA */
+					0x194 0x05	/* mcasp0_fsx.pr1_pru0_pru_r30_1, MODE5 | LATCH */
+					0x1a4 0x05	/* mcasp0_fsr.pr1_pru1_pru_r30_5, MODE5 | CLK */
+				>;
+			};
+		};
+	};
+
+	fragment@2 {
+		target = <&epwmss2>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@1 {
+		target = <&ehrpwm2>;
+		__overlay__ {
+			status = "okay";
+		};
+	};
+
+	fragment@3 {
+		target = <&ocp>;
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			gpio-leds-cape-nixie {
+				compatible = "gpio-leds";
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_nixie_cape_led_pins>;
+
+				nixie-led0 {
+					label = "nixie:green:usr0";
+					gpios = <&gpio4 21 0>;
+					linux,default-trigger = "nixie-run";
+					default-state = "off";
+				};
+			};
+
+			bone-cape-nixie {
+				compatible = "bone-cape-nixie";
+				status = "okay";
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&bone_nixie_cape_pins>;
+
+				pwms = <&ehrpwm2 0 500000 0>;
+				pwm-names = "bone-nixie-cape";
+
+				pwm-frequency  = <9250>;	/* 9.250KHz */
+				pwm-duty-cycle = <35>;		/* 35% */
+
+				default-brightness = <35>;	/* 35% */
+			};
+		};
+	};
+
+	fragment@4 {
+		target = <&pruss>;
+		__overlay__ {
+			status = "okay";
+
+			pinctrl-names = "default";
+			pinctrl-0 = <&pruss_pins>;
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-pinmux-test-00A0.dts b/firmware/capes/cape-bone-pinmux-test-00A0.dts
new file mode 100644
index 0000000..76c9656
--- /dev/null
+++ b/firmware/capes/cape-bone-pinmux-test-00A0.dts
@@ -0,0 +1,43 @@
+/*
+ * 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	/* identification */
+	part-number = "pinctrl-test";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			pinctrl_test_7: pinctrl_test_7_pins {
+				pinctrl-single,pins = <
+					0x164 0x07	/* P9_42 muxRegOffset, OUTPUT | MODE7 */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&ocp>;
+		__overlay__ {
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			test_helper: helper {
+				compatible = "bone-pinmux-helper";
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_test_7>;
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/firmware/capes/cape-bone-tester-00A0.dts b/firmware/capes/cape-bone-tester-00A0.dts
new file mode 100644
index 0000000..df04f6d
--- /dev/null
+++ b/firmware/capes/cape-bone-tester-00A0.dts
@@ -0,0 +1,486 @@
+/*
+ * Copyright (C) 2013 CircuitCo
+ *
+ * This program is free software; you can 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone";
+
+	/* identification */
+	part-number = "BB-BONE-TESTER";
+	version = "00A0";
+
+	/* NOTE: we don't use resources for the tester - it's not a normal cape */
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			/* default state has all gpios released and mode set to uart1 */
+			bone_tester_default_gpio_pins: pinmux_bone_tester_default_gpio_pins {
+				pinctrl-single,pins = <
+					/* the uart pins */
+					0x184 0x20 /* 24 UART1_TXD  uart1_txd  OUTPUT  */
+					0x180 0x20 /* 26 UART1_RXD  uart1_rxd  INPUT  */
+				>;
+			};
+			bone_tester_input_gpio_pins: pinmux_bone_tester_input_gpio_pins {
+				pinctrl-single,pins = <
+					/* P8 connector on the bone */
+					/* P3 - P46 pins, B_A3-B_A46, INPUT | PULLDIS | MODE7 */
+					0x018 0x2f /*  3 GPIO1_6    gpmc_ad6.gpio1[6]      */
+					0x01C 0x2f /*  4 GPIO1_7    gpmc_ad7.gpio1[7]      */
+					0x008 0x2f /*  5 GPIO1_2    gpmc_ad2.gpio1[2]      */
+					0x00C 0x2f /*  6 GPIO1_3    gpmc_ad3.gpio1[3]      */
+					0x090 0x2f /*  7 TIMER4     gpmc_advn_ale.gpio2[2] */
+					0x094 0x2f /*  8 TIMER7     gpmc_oen_ren.gpio2[3]  */
+					0x09C 0x2f /*  9 TIMER5     gpmc_ben0_cle.gpio2[5] */
+					0x098 0x2f /* 10 TIMER6     gpmc_wen.gpio2[4]      */
+					0x034 0x2f /* 11 GPIO1_13   gpmc_ad13.gpio1[13]    */
+					0x030 0x2f /* 12 GPIO1_12   gpmc_ad12.gpio1[12]    */
+					0x024 0x2f /* 13 EHRPWM2B   gpmc_ad9 .gpio0[23]    */
+					0x028 0x2f /* 14 GPIO0_26   gpmc_ad10.gpio0[26]    */
+					0x03C 0x2f /* 15 GPIO1_15   gpmc_ad15.gpio1[15]    */
+					0x038 0x2f /* 16 GPIO1_14   gpmc_ad14.gpio1[14]    */
+					0x02C 0x2f /* 17 GPIO0_27   gpmc_ad11.gpio0[27]    */
+					0x08C 0x2f /* 18 GPIO2_1    gpmc_clk .gpio2[1]     */
+					0x020 0x2f /* 19 EHRPWM2A   gpmc_ad8 .gpio0[22]    */
+					0x084 0x2f /* 20 GPIO1_31   gpmc_csn2.gpio1[31]    */
+					0x080 0x2f /* 21 GPIO1_30   gpmc_csn1.gpio1[30]    */
+					0x014 0x2f /* 22 GPIO1_5    gpmc_ad5 .gpio1[5]     */
+					0x010 0x2f /* 23 GPIO1_4    gpmc_ad4 .gpio1[4]     */
+					0x004 0x2f /* 24 GPIO1_1    gpmc_ad1 .gpio1[1]     */
+					0x000 0x2f /* 25 GPIO1_0    gpmc_ad0 .gpio1[0]     */
+					0x07C 0x2f /* 26 GPIO1_29   gpmc_csn0.gpio1[29]    */
+					// 0x0E0 0x2f /* 27 GPIO2_22   lcd_vsync.gpio2[22]    */
+					// 0x0E8 0x2f /* 28 GPIO2_24   lcd_pclk .gpio2[24]    */
+					// 0x0E4 0x2f /* 29 GPIO2_23   lcd_hsync.gpio2[23]    */
+					// 0x0EC 0x2f /* 30 GPIO2_25   lcd_ac_bias_en.gpio2[25] */
+					// 0x0D8 0x2f /* 31 UART5_CTSN lcd_data14.gpio0[10]   */
+					// 0x0DC 0x2f /* 32 UART5_RTSN lcd_data15.gpio0[11]   */
+					// 0x0D4 0x2f /* 33 UART4_RTSN lcd_data13.gpio0[9]    */
+					// 0x0CC 0x2f /* 34 UART3_RTSN lcd_data11.gpio2[17]   */
+					// 0x0D0 0x2f /* 35 UART4_CTSN lcd_data12.gpio0[8]    */
+					// 0x0C8 0x2f /* 36 UART3_CTSN lcd_data10.gpio2[16]   */
+					// 0x0C0 0x2f /* 37 UART5_TXD  lcd_data8.gpio2[14]    */
+					// 0x0C4 0x2f /* 38 UART5_RXD  lcd_data9.gpio2[15]    */
+					// 0x0B8 0x2f /* 39 GPIO2_12   lcd_data6.gpio2[12]    */
+					// 0x0BC 0x2f /* 40 GPIO2_13   lcd_data7.gpio2[13]    */
+					// 0x0B0 0x2f /* 41 GPIO2_10   lcd_data4.gpio2[10]    */
+					// 0x0B4 0x2f /* 42 GPIO2_11   lcd_data5.gpio2[11]    */
+					// 0x0A8 0x2f /* 43 GPIO2_8    lcd_data2.gpio2[8]     */
+					// 0x0AC 0x2f /* 44 GPIO2_9    lcd_data3.gpio2[9]     */
+					// 0x0A0 0x2f /* 45 GPIO2_6    lcd_data0.gpio2[6]     */
+					// 0x0A4 0x2f /* 46 GPIO2_7    lcd_data1.gpio2[7]     */
+
+					/* P9 connector on the bone */
+					/* B_B0-B_B19, INPUT | PULLDIS | MODE7 */
+					0x070 0x2f /* 11 UART4_RXD  gpmc_wait0.gpio0[30]   */
+					0x078 0x2f /* 12 GPIO1_28   gpmc_be1n.gpio1[28]    */
+					0x074 0x2f /* 13 UART4_TXD  gpmc_wpn.gpio0[31]     */
+					0x048 0x2f /* 14 EHRPWM1A   gpmc_a2.gpio1[18]      */
+					0x040 0x2f /* 15 GPIO1_16   gpmc_a0.gpio1[16]      */
+					0x04C 0x2f /* 16 EHRPWM1B   gpmc_a3.gpio1[19]      */
+
+					/* err, those two are used for I2C2 on the beaglebone */
+					/* you should boot with I2C2 disabled on the tester */
+					// 0x17C 0x2f /* 19 I2C2_SCL   uart1_rtsn.gpio0[13]   */
+					// 0x178 0x2f /* 20 I2C2_SDA   uart1_ctsn.gpio0[12]   */
+
+					0x154 0x2f /* 21 UART2_TXD  spi0_d0.gpio0[3]       */
+					0x150 0x2f /* 22 UART2_RXD  spi0_sclk.gpio0[2]     */
+					0x044 0x2f /* 23 GPIO1_17   gpmc_a1.gpio1[17]      */
+					0x1AC 0x2f /* 25 GPIO3_21   mcasp0_ahclkx.gpio3[21]*/
+					0x1A4 0x2f /* 27 GPIO3_19   mcasp0_fsr.gpio3[19]   */
+					0x19C 0x2f /* 28 SPI1_CS0   mcasp0_ahclkr.gpio3[17]*/
+					0x198 0x2f /* 30 SPI1_D1    mcasp0_axr0.gpio3[16]  */
+					0x190 0x2f /* 31 SPI1_SCLK  mcasp0_aclkx.gpio3[14] */
+					0x1B4 0x2f /* 41 CLKOUT2    xdma_event_intr1.gpio0[20]*/
+					0x164 0x2f /* 42 GPIO0_7    eCAP0_in_PWM0_out.gpio0[7]*/
+
+					/* the UART pins */
+					// 0x184 0x2f /* 24 UART1_TXD  uart1_txd.gpio0[15]    */
+					// 0x180 0x2f /* 26 UART1_RXD  uart1_rxd.gpio0[14]    */
+				>;
+			};
+
+			bone_tester_output_gpio_pins: pinmux_bone_tester_output_gpio_pins {
+				pinctrl-single,pins = <
+					/* P8 connector on the bone */
+					/* P3 - P46 pins, B_A3-B_A46, OUTPUT | MODE7 */
+					0x018 0x07 /*  3 GPIO1_6    gpmc_ad6.gpio1[6]      */
+					0x01C 0x07 /*  4 GPIO1_7    gpmc_ad7.gpio1[7]      */
+					0x008 0x07 /*  5 GPIO1_2    gpmc_ad2.gpio1[2]      */
+					0x00C 0x07 /*  6 GPIO1_3    gpmc_ad3.gpio1[3]      */
+					0x090 0x07 /*  7 TIMER4     gpmc_advn_ale.gpio2[2] */
+					0x094 0x07 /*  8 TIMER7     gpmc_oen_ren.gpio2[3]  */
+					0x09C 0x07 /*  9 TIMER5     gpmc_ben0_cle.gpio2[5] */
+					0x098 0x07 /* 10 TIMER6     gpmc_wen.gpio2[4]      */
+					0x034 0x07 /* 11 GPIO1_13   gpmc_ad13.gpio1[13]    */
+					0x030 0x07 /* 12 GPIO1_12   gpmc_ad12.gpio1[12]    */
+					0x024 0x07 /* 13 EHRPWM2B   gpmc_ad9 .gpio0[23]    */
+					0x028 0x07 /* 14 GPIO0_26   gpmc_ad10.gpio0[26]    */
+					0x03C 0x07 /* 15 GPIO1_15   gpmc_ad15.gpio1[15]    */
+					0x038 0x07 /* 16 GPIO1_14   gpmc_ad14.gpio1[14]    */
+					0x02C 0x07 /* 17 GPIO0_27   gpmc_ad11.gpio0[27]    */
+					0x08C 0x07 /* 18 GPIO2_1    gpmc_clk .gpio2[1]     */
+					0x020 0x07 /* 19 EHRPWM2A   gpmc_ad8 .gpio0[22]    */
+					0x084 0x07 /* 20 GPIO1_31   gpmc_csn2.gpio1[31]    */
+					0x080 0x07 /* 21 GPIO1_30   gpmc_csn1.gpio1[30]    */
+					0x014 0x07 /* 22 GPIO1_5    gpmc_ad5 .gpio1[5]     */
+					0x010 0x07 /* 23 GPIO1_4    gpmc_ad4 .gpio1[4]     */
+					0x004 0x07 /* 24 GPIO1_1    gpmc_ad1 .gpio1[1]     */
+					0x000 0x07 /* 25 GPIO1_0    gpmc_ad0 .gpio1[0]     */
+					0x07C 0x07 /* 26 GPIO1_29   gpmc_csn0.gpio1[29]    */
+					// 0x0E0 0x07 /* 27 GPIO2_22   lcd_vsync.gpio2[22]    */
+					// 0x0E8 0x07 /* 28 GPIO2_24   lcd_pclk .gpio2[24]    */
+					// 0x0E4 0x07 /* 29 GPIO2_23   lcd_hsync.gpio2[23]    */
+					// 0x0EC 0x07 /* 30 GPIO2_25   lcd_ac_bias_en.gpio2[25] */
+					// 0x0D8 0x07 /* 31 UART5_CTSN lcd_data14.gpio0[10]   */
+					// 0x0DC 0x07 /* 32 UART5_RTSN lcd_data15.gpio0[11]   */
+					// 0x0D4 0x07 /* 33 UART4_RTSN lcd_data13.gpio0[9]    */
+					// 0x0CC 0x07 /* 34 UART3_RTSN lcd_data11.gpio2[17]   */
+					// 0x0D0 0x07 /* 35 UART4_CTSN lcd_data12.gpio0[8]    */
+					// 0x0C8 0x07 /* 36 UART3_CTSN lcd_data10.gpio2[16]   */
+					// 0x0C0 0x07 /* 37 UART5_TXD  lcd_data8.gpio2[14]    */
+					// 0x0C4 0x07 /* 38 UART5_RXD  lcd_data9.gpio2[15]    */
+					// 0x0B8 0x07 /* 39 GPIO2_12   lcd_data6.gpio2[12]    */
+					// 0x0BC 0x07 /* 40 GPIO2_13   lcd_data7.gpio2[13]    */
+					// 0x0B0 0x07 /* 41 GPIO2_10   lcd_data4.gpio2[10]    */
+					// 0x0B4 0x07 /* 42 GPIO2_11   lcd_data5.gpio2[11]    */
+					// 0x0A8 0x07 /* 43 GPIO2_8    lcd_data2.gpio2[8]     */
+					// 0x0AC 0x07 /* 44 GPIO2_9    lcd_data3.gpio2[9]     */
+					// 0x0A0 0x07 /* 45 GPIO2_6    lcd_data0.gpio2[6]     */
+					// 0x0A4 0x07 /* 46 GPIO2_7    lcd_data1.gpio2[7]     */
+
+					/* P9 connector on the bone */
+					/* B_B0-B_B19, INPUT | PULLDIS | MODE7 */
+					0x070 0x07 /* 11 UART4_RXD  gpmc_wait0.gpio0[30]   */
+					0x078 0x07 /* 12 GPIO1_28   gpmc_be1n.gpio1[28]    */
+					0x074 0x07 /* 13 UART4_TXD  gpmc_wpn.gpio0[31]     */
+					0x048 0x07 /* 14 EHRPWM1A   gpmc_a2.gpio1[18]      */
+					0x040 0x07 /* 15 GPIO1_16   gpmc_a0.gpio1[16]      */
+					0x04C 0x07 /* 16 EHRPWM1B   gpmc_a3.gpio1[19]      */
+
+					/* err, those two are used for I2C2 on the beaglebone */
+					/* you should boot with I2C2 disabled on the tester */
+					// 0x17C 0x07 /* 19 I2C2_SCL   uart1_rtsn.gpio0[13]   */
+					// 0x178 0x07 /* 20 I2C2_SDA   uart1_ctsn.gpio0[12]   */
+
+					0x154 0x07 /* 21 UART2_TXD  spi0_d0.gpio0[3]       */
+					0x150 0x07 /* 22 UART2_RXD  spi0_sclk.gpio0[2]     */
+					0x044 0x07 /* 23 GPIO1_17   gpmc_a1.gpio1[17]      */
+					0x1AC 0x07 /* 25 GPIO3_21   mcasp0_ahclkx.gpio3[21]*/
+					0x1A4 0x07 /* 27 GPIO3_19   mcasp0_fsr.gpio3[19]   */
+					0x19C 0x07 /* 28 SPI1_CS0   mcasp0_ahclkr.gpio3[17]*/
+					0x198 0x07 /* 30 SPI1_D1    mcasp0_axr0.gpio3[16]  */
+					0x190 0x07 /* 31 SPI1_SCLK  mcasp0_aclkx.gpio3[14] */
+					0x1B4 0x07 /* 41 CLKOUT2    xdma_event_intr1.gpio0[20]*/
+					0x164 0x07 /* 42 GPIO0_7    eCAP0_in_PWM0_out.gpio0[7]*/
+
+					/* the uart pins */
+					// 0x184 0x07 /* 24 UART1_TXD  uart1_txd.gpio0[15]    */
+					// 0x180 0x07 /* 26 UART1_RXD  uart1_rxd.gpio0[14]    */
+				>;
+			};
+
+			bone_tester_i2c1_pins: pinmux_bone_tester_i2c1_pins {
+				pinctrl-single,pins = <
+					0x158 0x72	/* spi0_d1.i2c1_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
+					0x15c 0x72	/* spi0_cs0.i2c1_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE2 */
+				>;
+			};
+
+			bone_tester_jhd629_pins: pinmux_bone_tester_jhd629_pins {
+				pinctrl-single,pins = <
+					0x194 0x37 	/* mcasp0_fsx.gpio3_15, OMAP_MUX_MODE7 | INPUT_PULLUP */
+				>;
+			};
+
+			bone_default_drvvbus_pins: pinmux_bone_default_drvvbus_pins {
+				pinctrl-single,pins = <
+					0x234 0x20 /* USB1_DRVVBUS musb  */
+				>;
+			};
+			bone_gpio_drvvbus_pins: pinmux_bone_gpio_drvvbus_pins {
+				pinctrl-single,pins = <
+					0x234 0x07 /* USB1_DRVVBUS.gpio3_13  OUTPUT  */
+				>;
+			};
+		};
+	};
+
+	fragment@1 {
+		target = <&i2c1>;
+		__overlay__ {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&bone_tester_i2c1_pins>;
+			status = "okay";
+			clock-frequency = <100000>;
+		};
+	};
+
+	fragment@2 {
+		target = <&i2c1>;
+		__overlay__ {
+			/* needed to avoid gripping by DTC */
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* pca9457 */
+			pca9457_mux {
+				compatible = "nxp,pca9547";
+				status = "okay";
+
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x70>;
+
+				bus@0 {	/* LCD/KEY */
+					compatible = "nxp,pca954x-bus";
+					status = "okay";
+					nxp,pca95x-class = <0x0>;
+					reg = <0x0>;
+					nxp,deselect-on-exit;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					jhd629@31 {
+						compatible = "jhd,jhd629";
+						status = "okay";
+						reg = <0x31>;
+
+						pinctrl-names = "default";
+						pinctrl-0 = <&bone_tester_jhd629_pins>;
+
+						rows = <4>;
+						columns = <20>;
+						keymap = "123A456B789C*0#D";
+						poll-period = <250>;	/* poll every 250ms */
+						// gpios = <&gpio4 15 0>;	/* keypad interrupt */
+					};
+				};
+
+				bus@1 {	/* LATCH */
+					compatible = "nxp,pca954x-bus";
+					status = "okay";
+					nxp,pca95x-class = <0x0>;
+					reg = <0x1>;
+					nxp,deselect-on-exit;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					tester_latch: latch@38 {
+						/*
+						 * TESTING_LED
+						 * FAILED_LED
+						 * ATTN_LED
+						 * RDY_LED
+						 * DC_RELAY
+						 * PWRBUT_RELAY
+						 * RESET_RELAY
+						 */
+						compatible = "nxp,pcf8574";
+						status = "okay";
+						reg = <0x38>;
+						gpio-controller;
+						#gpio-cells = <2>;
+
+					};
+				};
+
+				bus@2 {	/* SOLENOIDS */
+					compatible = "nxp,pca954x-bus";
+					status = "okay";
+					nxp,pca95x-class = <0x0>;
+					reg = <0x2>;
+					nxp,deselect-on-exit;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					grove@f {
+						compatible = "grove";
+						status = "okay";
+						reg = <0x0f>;
+					};
+				};
+
+				bus@3 {	/* RTC */
+					compatible = "nxp,pca954x-bus";
+					status = "okay";
+					nxp,pca95x-class = <0x0>;
+					reg = <0x3>;
+					nxp,deselect-on-exit;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					rtc@68 {
+						compatible = "dallas,ds1307";
+						status = "okay";
+						reg = <0x68>;
+					};
+				};
+
+				bus@4 {	/* INA219 */
+					compatible = "nxp,pca954x-bus";
+					status = "okay";
+					nxp,pca95x-class = <0x0>;
+					reg = <0x4>;
+					nxp,deselect-on-exit;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					ina@40 {
+						compatible = "ti,ina219";
+						status = "okay";
+						reg = <0x40>;
+					};
+				};
+
+				bus@5 {	/* BUFFERS */
+					compatible = "nxp,pca954x-bus";
+					status = "okay";
+					nxp,pca95x-class = <0x0>;
+					reg = <0x5>;
+					nxp,deselect-on-exit;
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					tester_buffers: latch@39 {
+						/*
+						 * TxD_BUFFER
+						 * RxD_BUFFER
+						 * OE_BUFFER
+						 * DIR_BUFFER
+						 * CTRL_EEPROM_WP
+						 */
+						compatible = "nxp,pcf8574";
+						status = "okay";
+						reg = <0x39>;
+						gpio-controller;
+						#gpio-cells = <2>;
+					};
+				};
+			};
+		};
+	};
+
+	fragment@3 {
+		target = <&ocp>;
+		__overlay__ {
+
+			gpio-leds-tester {
+				compatible = "gpio-leds";
+
+				/* note we don't use tester:<color>:<function> */
+				led0 {
+					label = "TESTING_LED";
+					gpios = <&tester_latch 0 0>;
+					linux,default-trigger = "none";
+					default-state = "off";
+				};
+
+				led1 {
+					label = "FAILED_LED";
+					gpios = <&tester_latch 1 0>;
+					linux,default-trigger = "none";
+					default-state = "off";
+				};
+
+				led2 {
+					label = "PASS_LED";
+					gpios = <&tester_latch 2 0>;
+					linux,default-trigger = "none";
+					default-state = "off";
+				};
+
+				led3 {
+					label = "ATTN_LED";
+					gpios = <&tester_latch 3 0>;
+					linux,default-trigger = "none";
+					default-state = "off";
+				};
+
+				led4 {
+					label = "RDY_LED";
+					gpios = <&tester_latch 4 0>;
+					linux,default-trigger = "none";
+					default-state = "off";
+				};
+			};
+		};
+
+	};
+
+	fragment@4 {
+		target = <&ocp>;
+		__overlay__ {
+
+			tester_pinmux_helper {
+				compatible = "bone-pinmux-helper";
+				status = "okay";
+
+				pinctrl-names = "default", "input", "output";
+				pinctrl-0 = <&bone_tester_default_gpio_pins>;
+				pinctrl-1 = <&bone_tester_input_gpio_pins>;
+				pinctrl-2 = <&bone_tester_output_gpio_pins>;
+			};
+
+			drvvbus_pinmux_helper {
+				compatible = "bone-pinmux-helper";
+				status = "okay";
+
+				pinctrl-names = "default", "gpio";
+				pinctrl-0 = <&bone_default_drvvbus_pins>;
+				pinctrl-1 = <&bone_gpio_drvvbus_pins>;
+			};
+		};
+
+	};
+
+	fragment@5 {
+		target = <&uart2>;	/* really uart1 */
+		__overlay__ {
+			/* please note that the pinconfig is done by the pinmux helper */
+			status = "okay";
+		};
+	};
+
+	fragment@6 {
+		target = <&ocp>;
+		__overlay__ {
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			tscadc {
+				compatible = "ti,ti-tscadc";
+				reg = <0x44e0d000 0x1000>;
+
+				interrupt-parent = <&intc>;
+				interrupts = <16>;
+				ti,hwmods = "adc_tsc";
+				status = "okay";
+
+				adc {
+					ti,adc-channels = <0 1 2 3 4 5 6 7>;
+				};
+			};
+
+			tester_iio_helper {
+				compatible = "bone-iio-helper";
+				vsense-name  = "AIN0", "AIN1", "AIN2", "AIN3", "AIN4", "AIN5", "AIN6", "AIN7";
+				vsense-scale = <100     100     100     100     100     100     100     100>;
+				// vsense-scale = <200     200     296     296     296     296     100     100>;
+					      /* 3.3V   3.3V    5V      5V      5V      5V      1.8V */
+				status = "okay";
+			};
+		};
+	};
+};
+
diff --git a/firmware/capes/cape-bone-weather-00A0.dts b/firmware/capes/cape-bone-weather-00A0.dts
new file mode 100644
index 0000000..c017cdb
--- /dev/null
+++ b/firmware/capes/cape-bone-weather-00A0.dts
@@ -0,0 +1,76 @@
+/*
+* 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/;
+/plugin/;
+
+/ {
+	compatible = "ti,beaglebone", "ti,beaglebone-black";
+
+	part-number = "BB-BONE-WTHR-01";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.6",		/* gpio1_3 */
+		/* the hardware IP uses */
+		"gpio1_3";
+
+	fragment@0 {
+               target = <&am33xx_pinmux>;
+               __overlay__ {
+			weather_cape_w1_pins: pinmux_weather_cape_w1_pins {
+				pinctrl-single,pins = <
+					0x0c 0x37       /* gpmc_ad3.gpio1_3, OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE7 - w1-gpio */
+				>;
+			};
+               };
+	};
+
+	fragment@1 {
+               target = <&i2c2>;
+
+               __overlay__ {
+		       /* needed to avoid gripping by DTC */
+		       #address-cells = <1>;
+		       #size-cells = <0>;
+
+		       /* Ambient light sensor */
+		       tsl2550@39 {
+			       compatible = "tsl,tsl2550";
+			       reg = <0x39>;
+		       };
+
+		       /* Humidity Sensor */
+		       sht21@40 {
+			       compatible = "sensiron,sht21";
+			       reg = <0x40>;
+		       };
+
+		       /* Barometric pressure sensor */
+		       bmp085@77 {
+			       compatible = "bosch,bmp085";
+			       reg = <0x77>;
+		       };
+               };
+	};
+
+	fragment@2 {
+               target = <&ocp>;
+               __overlay__ {
+		       onewire@0 {
+			       compatible      = "w1-gpio";
+			       pinctrl-names   = "default";
+			       pinctrl-0       = <&weather_cape_w1_pins>;
+			       status          = "okay";
+
+			       gpios = <&gpio2 3 0>;
+		       };
+               };
+	};
+};
diff --git a/firmware/capes/cape-boneblack-hdmi-00A0.dts b/firmware/capes/cape-boneblack-hdmi-00A0.dts
new file mode 100644
index 0000000..04b7b54
--- /dev/null
+++ b/firmware/capes/cape-boneblack-hdmi-00A0.dts
@@ -0,0 +1,188 @@
+/*
+* 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/;
+/plugin/;
+
+/ {
+  	compatible = "ti,beaglebone-black";
+	part-number = "BB-BONELT-HDMI";
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P9.25",	/* mcasp0: mcasp0_ahclkx */
+		"P9.28",	/* mcasp0: mcasp0_axr2 */
+		"P9.29",	/* mcasp0: mcasp0_fsx */
+		"P9.31",	/* mcasp0: mcasp0_aclkx */
+		"P8.45",	/* lcd: lcd_data0 */
+		"P8.46",	/* lcd: lcd_data1 */
+		"P8.43",	/* lcd: lcd_data2 */
+		"P8.44",	/* lcd: lcd_data3 */
+		"P8.41",	/* lcd: lcd_data4 */
+		"P8.42",	/* lcd: lcd_data5 */
+		"P8.39",	/* lcd: lcd_data6 */
+		"P8.40",	/* lcd: lcd_data7 */
+		"P8.37",	/* lcd: lcd_data8 */
+		"P8.38",	/* lcd: lcd_data9 */
+		"P8.36",	/* lcd: lcd_data10 */
+		"P8.34",	/* lcd: lcd_data11 */
+		"P8.35",	/* lcd: lcd_data12 */
+		"P8.33",	/* lcd: lcd_data13 */
+		"P8.31",	/* lcd: lcd_data14 */
+		"P8.32",	/* lcd: lcd_data15 */
+		"P8.27",	/* lcd: lcd_vsync */
+		"P8.29",	/* lcd: lcd_hsync */
+		"P8.28",	/* lcd: lcd_pclk */
+		"P8.30",	/* lcd: lcd_ac_bias_en */
+		/* the hardware IP uses */
+		"gpio1_27",
+		"mcasp0",
+		"lcd";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+				pinctrl-single,pins = <
+					0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
+					0xa0 0x08       /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa4 0x08       /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa8 0x08       /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xac 0x08       /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb0 0x08       /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb4 0x08       /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb8 0x08       /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xbc 0x08       /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc0 0x08       /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc4 0x08       /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc8 0x08       /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xcc 0x08       /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd0 0x08       /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd4 0x08       /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd8 0x08       /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xdc 0x08       /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xe0 0x00       /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe4 0x00       /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe8 0x00       /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xec 0x00       /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+			nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+				pinctrl-single,pins = <
+					0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+
+			mcasp0_pins: mcasp0_pins {
+				pinctrl-single,pins = <
+					0x1ac 0x30      /* mcasp0_ahclkx,       MODE0 | INPUT */
+					0x19c 0x02	/* mcasp0_ahclkr, */
+					0x194 0x10      /* mcasp0_fsx,         MODE0 | OUTPUT  */
+					0x190 0x00      /* mcasp0_aclkr.mcasp0_aclkx,     MODE0 | OUTPUT_PULLDOWN */
+					0x1a8 0x1f	/* mcasp0_axr1 GPIO1_27 | OUTPUT | PULLUP */
+				>;
+			};
+		};
+	};
+
+	fragment@2 {
+		target = <&ocp>;
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			nxptda: nxptda@0 {
+			       compatible = "nxp,nxptda";
+			       status = "okay";
+			};
+
+			hdmi {
+				compatible = "tilcdc,slave";
+				i2c = <&i2c0>;
+				pinctrl-names = "default", "off";
+				pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+				pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
+				modes-blacklisted =
+					"1920x1080@25",
+					"832x624@75";
+
+				// Enable this when we figure out the modes
+				//
+				// modes-whitelisted =
+				//	"1920x1080@24",
+				//	"1280x720@50", "1280x720@60",
+				//	"720x576@50","720x480@60";
+
+				panel-info {
+					bpp = <16>;
+					ac-bias = <255>;
+					ac-bias-intrpt = <0>;
+					dma-burst-sz = <16>;
+					fdd = <16>;
+					sync-edge = <1>;
+					sync-ctrl = <1>;
+					raster-order = <0>;
+					fifo-th = <0>;
+					invert-pxl-clk;
+				};
+			};
+
+			fb {
+				compatible = "ti,am33xx-tilcdc";
+				reg = <0x4830e000 0x1000>;
+				interrupt-parent = <&intc>;
+				interrupts = <36>;
+				ti,hwmods = "lcdc";
+				ti,allow-non-reduced-blanking-modes;
+			};
+
+		};
+	};
+
+	fragment@3 {
+		target = <&mcasp0>;
+		__overlay__ {
+			pinctrl-names = "default";
+			pinctrl-0 = <&mcasp0_pins>;
+
+			status = "okay";
+
+			op-mode = <0>;          /* MCASP_IIS_MODE */
+			tdm-slots = <2>;
+			num-serializer = <16>;
+			serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+				0 0 1 0
+				0 0 0 0
+				0 0 0 0
+				0 0 0 0
+			>;
+			tx-num-evt = <1>;
+			rx-num-evt = <1>;
+		};
+	};
+
+	fragment@4 {
+		target = <&ocp>;
+		__overlay__ {
+			sound {
+				compatible = "ti,am33xx-beaglebone-black";
+				ti,model = "TI BeagleBone Black";
+				ti,audio-codec = <&nxptda>;
+				ti,mcasp-controller = <&mcasp0>;
+				ti,codec-clock-rate = <2457600>;
+				mcasp_clock_enable = <&gpio2 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
+			};
+		};
+
+	};
+
+};
diff --git a/firmware/capes/cape-boneblack-hdmin-00A0.dts b/firmware/capes/cape-boneblack-hdmin-00A0.dts
new file mode 100644
index 0000000..ad55c4d
--- /dev/null
+++ b/firmware/capes/cape-boneblack-hdmin-00A0.dts
@@ -0,0 +1,136 @@
+/*
+* 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/;
+/plugin/;
+
+/ {
+  	compatible = "ti,beaglebone-black";
+	part-number = "BB-BONELT-HDMIN";	/* No audio */
+	version = "00A0";
+
+	/* state the resources this cape uses */
+	exclusive-use =
+		/* the pin header uses */
+		"P8.45",	/* lcd: lcd_data0 */
+		"P8.46",	/* lcd: lcd_data1 */
+		"P8.43",	/* lcd: lcd_data2 */
+		"P8.44",	/* lcd: lcd_data3 */
+		"P8.41",	/* lcd: lcd_data4 */
+		"P8.42",	/* lcd: lcd_data5 */
+		"P8.39",	/* lcd: lcd_data6 */
+		"P8.40",	/* lcd: lcd_data7 */
+		"P8.37",	/* lcd: lcd_data8 */
+		"P8.38",	/* lcd: lcd_data9 */
+		"P8.36",	/* lcd: lcd_data10 */
+		"P8.34",	/* lcd: lcd_data11 */
+		"P8.35",	/* lcd: lcd_data12 */
+		"P8.33",	/* lcd: lcd_data13 */
+		"P8.31",	/* lcd: lcd_data14 */
+		"P8.32",	/* lcd: lcd_data15 */
+		"P8.27",	/* lcd: lcd_vsync */
+		"P8.29",	/* lcd: lcd_hsync */
+		"P8.28",	/* lcd: lcd_pclk */
+		"P8.30",	/* lcd: lcd_ac_bias_en */
+		/* the hardware IP uses */
+		"gpio1_27",
+		"lcd";
+
+	fragment@0 {
+		target = <&am33xx_pinmux>;
+		__overlay__ {
+			nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+				pinctrl-single,pins = <
+					0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
+					0xa0 0x08       /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa4 0x08       /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xa8 0x08       /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xac 0x08       /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb0 0x08       /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb4 0x08       /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xb8 0x08       /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xbc 0x08       /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc0 0x08       /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc4 0x08       /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xc8 0x08       /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xcc 0x08       /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd0 0x08       /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd4 0x08       /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xd8 0x08       /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xdc 0x08       /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+					0xe0 0x00       /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe4 0x00       /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xe8 0x00       /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+					0xec 0x00       /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+			nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+				pinctrl-single,pins = <
+					0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
+				>;
+			};
+		};
+	};
+
+	fragment@2 {
+		target = <&ocp>;
+		__overlay__ {
+
+			/* avoid stupid warning */
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			nxptda: nxptda@0 {
+			       compatible = "nxp,nxptda";
+			       status = "okay";
+			};
+
+			hdmi {
+				compatible = "tilcdc,slave";
+				i2c = <&i2c0>;
+				pinctrl-names = "default", "off";
+				pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+				pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
+				modes-blacklisted =
+					"1920x1080@25",
+					"832x624@75";
+
+				// Enable this when we figure out the modes
+				//
+				// modes-whitelisted =
+				//	"1920x1080@24",
+				//	"1280x720@50", "1280x720@60",
+				//	"720x576@50","720x480@60";
+
+				panel-info {
+					bpp = <16>;
+					ac-bias = <255>;
+					ac-bias-intrpt = <0>;
+					dma-burst-sz = <16>;
+					fdd = <16>;
+					sync-edge = <1>;
+					sync-ctrl = <1>;
+					raster-order = <0>;
+					fifo-th = <0>;
+					invert-pxl-clk;
+				};
+			};
+
+			fb {
+				compatible = "ti,am33xx-tilcdc";
+				reg = <0x4830e000 0x1000>;
+				interrupt-parent = <&intc>;
+				interrupts = <36>;
+				ti,hwmods = "lcdc";
+				ti,allow-non-reduced-blanking-modes;
+				ti,allow-non-audio-modes;
+			};
+
+		};
+	};
+};
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 881fb15..98efdde 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -85,6 +85,9 @@ struct module;
 struct drm_file;
 struct drm_device;
 
+struct device_node;
+struct videomode;
+
 #include <drm/drm_os_linux.h>
 #include <drm/drm_hashtab.h>
 #include <drm/drm_mm.h>
@@ -1456,6 +1459,12 @@ extern struct drm_display_mode *
 drm_mode_create_from_cmdline_mode(struct drm_device *dev,
 				  struct drm_cmdline_mode *cmd);
 
+extern int drm_display_mode_from_videomode(const struct videomode *vm,
+					   struct drm_display_mode *dmode);
+extern int of_get_drm_display_mode(struct device_node *np,
+				   struct drm_display_mode *dmode,
+				   int index);
+
 /* Modesetting support */
 extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
 extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc);
diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h
index b0c11a7..8b9cc36 100644
--- a/include/drm/drm_encoder_slave.h
+++ b/include/drm/drm_encoder_slave.h
@@ -159,4 +159,24 @@ static inline void drm_i2c_encoder_unregister(struct drm_i2c_encoder_driver *dri
 
 void drm_i2c_encoder_destroy(struct drm_encoder *encoder);
 
+
+/*
+ * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs:
+ */
+
+void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode);
+bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder,
+		const struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode);
+void drm_i2c_encoder_prepare(struct drm_encoder *encoder);
+void drm_i2c_encoder_commit(struct drm_encoder *encoder);
+void drm_i2c_encoder_mode_set(struct drm_encoder *encoder,
+		struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode);
+enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder,
+	    struct drm_connector *connector);
+void drm_i2c_encoder_save(struct drm_encoder *encoder);
+void drm_i2c_encoder_restore(struct drm_encoder *encoder);
+
+
 #endif
diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
index 76c7098..4a3fc24 100644
--- a/include/drm/drm_fb_cma_helper.h
+++ b/include/drm/drm_fb_cma_helper.h
@@ -23,5 +23,10 @@ struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev,
 struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
 	unsigned int plane);
 
+#ifdef CONFIG_DEBUG_FS
+void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m);
+int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg);
+#endif
+
 #endif
 
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
index f0f6b1a..63397ce 100644
--- a/include/drm/drm_gem_cma_helper.h
+++ b/include/drm/drm_gem_cma_helper.h
@@ -41,4 +41,8 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
 
 extern const struct vm_operations_struct drm_gem_cma_vm_ops;
 
+#ifdef CONFIG_DEBUG_FS
+void drm_gem_cma_describe(struct drm_gem_cma_object *obj, struct seq_file *m);
+#endif
+
 #endif /* __DRM_GEM_CMA_HELPER_H__ */
diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h
new file mode 100644
index 0000000..23736f1
--- /dev/null
+++ b/include/drm/i2c/tda998x.h
@@ -0,0 +1,26 @@
+#ifndef __TDA998X_H__
+#define __TDA998X_H__
+
+#include <linux/types.h>
+
+enum tda998x_audio_format {
+	AFMT_I2S,
+	AFMT_SPDIF,
+};
+
+struct tda998x_encoder_params {
+	uint8_t audio_cfg;
+	uint8_t audio_clk_cfg;
+	enum tda998x_audio_format audio_format;
+	int audio_sample_rate;
+	uint8_t audio_frame[6];
+	uint8_t swap_a, mirr_a;
+	uint8_t swap_b, mirr_b;
+	uint8_t swap_c, mirr_c;
+	uint8_t swap_d, mirr_d;
+	uint8_t swap_e, mirr_e;
+	uint8_t swap_f, mirr_f;
+	uint8_t i2s_fmt;
+};
+
+#endif
diff --git a/include/linux/can/platform/mcp251x.h b/include/linux/can/platform/mcp251x.h
index 089fe43..c017922 100644
--- a/include/linux/can/platform/mcp251x.h
+++ b/include/linux/can/platform/mcp251x.h
@@ -13,6 +13,8 @@
  * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data
  * @oscillator_frequency:       - oscillator frequency in Hz
  * @irq_flags:                  - IRQF configuration flags
+ * @stay_awake:			- avoid entering sleep mode
+ * @enable_clkout:		- enable clock output
  * @board_specific_setup:       - called before probing the chip (power,reset)
  * @transceiver_enable:         - called to power on/off the transceiver
  * @power_enable:               - called to power on/off the mcp *and* the
@@ -26,6 +28,8 @@
 struct mcp251x_platform_data {
 	unsigned long oscillator_frequency;
 	unsigned long irq_flags;
+	bool stay_awake;
+	bool enable_clkout;
 	int (*board_specific_setup)(struct spi_device *spi);
 	int (*transceiver_enable)(int enable);
 	int (*power_enable) (int enable);
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index 9c7f580..942a1be 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -105,7 +105,8 @@ struct clk {
 
 #define _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,	\
 				_flags, _reg, _shift, _width,	\
-				_divider_flags, _table, _lock)	\
+				_min_div, _divider_flags,	\
+				_table, _lock)			\
 	static struct clk _name;				\
 	static const char *_name##_parent_names[] = {		\
 		_parent_name,					\
@@ -120,6 +121,7 @@ struct clk {
 		.reg = _reg,					\
 		.shift = _shift,				\
 		.width = _width,				\
+		.min_div = _min_div,				\
 		.flags = _divider_flags,			\
 		.table = _table,				\
 		.lock = _lock,					\
@@ -132,6 +134,7 @@ struct clk {
 				_divider_flags, _lock)		\
 	_DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,	\
 				_flags, _reg, _shift, _width,	\
+				CLK_DIVIDER_MIN_DIV_DEFAULT,	\
 				_divider_flags, NULL, _lock)
 
 #define DEFINE_CLK_DIVIDER_TABLE(_name, _parent_name,		\
@@ -140,6 +143,7 @@ struct clk {
 				_table, _lock)			\
 	_DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,	\
 				_flags, _reg, _shift, _width,	\
+				CLK_DIVIDER_MIN_DIV_DEFAULT,	\
 				_divider_flags, _table, _lock)	\
 
 #define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags,	\
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 4989b8a..8c6dadc 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -248,15 +248,22 @@ struct clk_divider {
 	void __iomem	*reg;
 	u8		shift;
 	u8		width;
+	u8		min_div;
 	u8		flags;
 	const struct clk_div_table	*table;
 	spinlock_t	*lock;
 };
 
+#define	CLK_DIVIDER_MIN_DIV_DEFAULT	1
+
 #define CLK_DIVIDER_ONE_BASED		BIT(0)
 #define CLK_DIVIDER_POWER_OF_TWO	BIT(1)
 
 extern const struct clk_ops clk_divider_ops;
+struct clk *clk_register_min_divider(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width, u8 min_div,
+		u8 clk_divider_flags, spinlock_t *lock);
 struct clk *clk_register_divider(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
@@ -362,6 +369,8 @@ void __clk_unprepare(struct clk *clk);
 void __clk_reparent(struct clk *clk, struct clk *new_parent);
 unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
 
+int __clk_set_parent(struct clk *clk, struct clk *parent);
+
 struct of_device_id;
 
 typedef void (*of_clk_init_cb_t)(struct device_node *);
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index d3201e4..64f9f69 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -371,6 +371,26 @@ struct dma_slave_config {
 	unsigned int slave_id;
 };
 
+/* struct dmaengine_chan_caps - expose capability of a channel
+ * Note: each channel can have same or different capabilities
+ *
+ * This primarily classifies capabilities into
+ * a) APIs/ops supported
+ * b) channel physical capabilities
+ *
+ * @cap_mask: api/ops capability (DMA_INTERRUPT and DMA_PRIVATE
+ *	       are invalid api/ops and will never be set)
+ * @seg_nr: maximum number of SG segments supported on a SG/SLAVE
+ *	    channel (0 for no maximum or not a SG/SLAVE channel)
+ * @seg_len: maximum length of SG segments supported on a SG/SLAVE
+ *	     channel (0 for no maximum or not a SG/SLAVE channel)
+ */
+struct dmaengine_chan_caps {
+	dma_cap_mask_t cap_mask;
+	int seg_nr;
+	int seg_len;
+};
+
 static inline const char *dma_chan_name(struct dma_chan *chan)
 {
 	return dev_name(&chan->dev->device);
@@ -534,6 +554,7 @@ struct dma_tx_state {
  *	struct with auxiliary transfer status information, otherwise the call
  *	will just return a simple status code
  * @device_issue_pending: push pending transactions to hardware
+ * @device_channel_caps: return the channel capabilities
  */
 struct dma_device {
 
@@ -602,6 +623,8 @@ struct dma_device {
 					    dma_cookie_t cookie,
 					    struct dma_tx_state *txstate);
 	void (*device_issue_pending)(struct dma_chan *chan);
+	struct dmaengine_chan_caps *(*device_channel_caps)(
+		struct dma_chan *chan, enum dma_transfer_direction direction);
 };
 
 static inline int dmaengine_device_control(struct dma_chan *chan,
@@ -969,11 +992,29 @@ dma_set_tx_state(struct dma_tx_state *st, dma_cookie_t last, dma_cookie_t used,
 	}
 }
 
+/**
+ * dma_get_channel_caps - flush pending transactions to HW
+ * @chan: target DMA channel
+ * @dir: direction of transfer
+ *
+ * Get the channel-specific capabilities. If the dmaengine
+ * driver does not implement per channel capbilities then
+ * NULL is returned.
+ */
+static inline struct dmaengine_chan_caps
+*dma_get_channel_caps(struct dma_chan *chan, enum dma_transfer_direction dir)
+{
+	if (chan->device->device_channel_caps)
+		return chan->device->device_channel_caps(chan, dir);
+	return NULL;
+}
+
 enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
 #ifdef CONFIG_DMA_ENGINE
 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 +1029,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)
 {
 }
@@ -1001,6 +1047,16 @@ void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
 struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type);
 struct dma_chan *net_dma_find_channel(void);
 #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
+static inline struct dma_chan
+*dma_request_slave_channel_compat(dma_cap_mask_t mask, dma_filter_fn fn,
+				  void *fn_param, struct device *dev,
+				  char *name)
+{
+	if (dev->of_node)
+		return dma_request_slave_channel(dev, name);
+	else
+		return dma_request_channel(mask, fn, fn_param);
+}
 
 /* --- Helper iov-locking functions --- */
 
diff --git a/include/linux/fb.h b/include/linux/fb.h
index c7a9571..0ce30d1 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -19,6 +19,8 @@ struct vm_area_struct;
 struct fb_info;
 struct device;
 struct file;
+struct videomode;
+struct device_node;
 
 /* Definitions below are used in the parsed monitor specs */
 #define FB_DPMS_ACTIVE_OFF	1
@@ -714,6 +716,22 @@ extern void fb_destroy_modedb(struct fb_videomode *modedb);
 extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
 extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
 
+#if defined(CONFIG_OF_VIDEOMODE) && defined(CONFIG_FB_MODE_HELPERS)
+extern int of_get_fb_videomode(struct device_node *np,
+			       struct fb_videomode *fb,
+			       int index);
+#else
+static inline int of_get_fb_videomode(struct device_node *np,
+				      struct fb_videomode *fb,
+				      int index)
+{
+	return -EINVAL;
+}
+#endif
+
+extern int fb_videomode_from_videomode(const struct videomode *vm,
+				       struct fb_videomode *fbmode);
+
 /* drivers/video/modedb.c */
 #define VESA_MODEDB_SIZE 34
 extern void fb_var_to_videomode(struct fb_videomode *mode,
diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h
new file mode 100644
index 0000000..3b58944
--- /dev/null
+++ b/include/linux/hdmi.h
@@ -0,0 +1,231 @@
+/*
+ * 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.
+ */
+
+#ifndef __LINUX_HDMI_H_
+#define __LINUX_HDMI_H_
+
+#include <linux/types.h>
+
+enum hdmi_infoframe_type {
+	HDMI_INFOFRAME_TYPE_VENDOR = 0x81,
+	HDMI_INFOFRAME_TYPE_AVI = 0x82,
+	HDMI_INFOFRAME_TYPE_SPD = 0x83,
+	HDMI_INFOFRAME_TYPE_AUDIO = 0x84,
+};
+
+#define HDMI_INFOFRAME_HEADER_SIZE  4
+#define HDMI_AVI_INFOFRAME_SIZE    13
+#define HDMI_SPD_INFOFRAME_SIZE    25
+#define HDMI_AUDIO_INFOFRAME_SIZE  10
+
+enum hdmi_colorspace {
+	HDMI_COLORSPACE_RGB,
+	HDMI_COLORSPACE_YUV422,
+	HDMI_COLORSPACE_YUV444,
+};
+
+enum hdmi_scan_mode {
+	HDMI_SCAN_MODE_NONE,
+	HDMI_SCAN_MODE_OVERSCAN,
+	HDMI_SCAN_MODE_UNDERSCAN,
+};
+
+enum hdmi_colorimetry {
+	HDMI_COLORIMETRY_NONE,
+	HDMI_COLORIMETRY_ITU_601,
+	HDMI_COLORIMETRY_ITU_709,
+	HDMI_COLORIMETRY_EXTENDED,
+};
+
+enum hdmi_picture_aspect {
+	HDMI_PICTURE_ASPECT_NONE,
+	HDMI_PICTURE_ASPECT_4_3,
+	HDMI_PICTURE_ASPECT_16_9,
+};
+
+enum hdmi_active_aspect {
+	HDMI_ACTIVE_ASPECT_16_9_TOP = 2,
+	HDMI_ACTIVE_ASPECT_14_9_TOP = 3,
+	HDMI_ACTIVE_ASPECT_16_9_CENTER = 4,
+	HDMI_ACTIVE_ASPECT_PICTURE = 8,
+	HDMI_ACTIVE_ASPECT_4_3 = 9,
+	HDMI_ACTIVE_ASPECT_16_9 = 10,
+	HDMI_ACTIVE_ASPECT_14_9 = 11,
+	HDMI_ACTIVE_ASPECT_4_3_SP_14_9 = 13,
+	HDMI_ACTIVE_ASPECT_16_9_SP_14_9 = 14,
+	HDMI_ACTIVE_ASPECT_16_9_SP_4_3 = 15,
+};
+
+enum hdmi_extended_colorimetry {
+	HDMI_EXTENDED_COLORIMETRY_XV_YCC_601,
+	HDMI_EXTENDED_COLORIMETRY_XV_YCC_709,
+	HDMI_EXTENDED_COLORIMETRY_S_YCC_601,
+	HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601,
+	HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB,
+};
+
+enum hdmi_quantization_range {
+	HDMI_QUANTIZATION_RANGE_DEFAULT,
+	HDMI_QUANTIZATION_RANGE_LIMITED,
+	HDMI_QUANTIZATION_RANGE_FULL,
+};
+
+/* non-uniform picture scaling */
+enum hdmi_nups {
+	HDMI_NUPS_UNKNOWN,
+	HDMI_NUPS_HORIZONTAL,
+	HDMI_NUPS_VERTICAL,
+	HDMI_NUPS_BOTH,
+};
+
+enum hdmi_ycc_quantization_range {
+	HDMI_YCC_QUANTIZATION_RANGE_LIMITED,
+	HDMI_YCC_QUANTIZATION_RANGE_FULL,
+};
+
+enum hdmi_content_type {
+	HDMI_CONTENT_TYPE_NONE,
+	HDMI_CONTENT_TYPE_PHOTO,
+	HDMI_CONTENT_TYPE_CINEMA,
+	HDMI_CONTENT_TYPE_GAME,
+};
+
+struct hdmi_avi_infoframe {
+	enum hdmi_infoframe_type type;
+	unsigned char version;
+	unsigned char length;
+	enum hdmi_colorspace colorspace;
+	bool active_info_valid;
+	bool horizontal_bar_valid;
+	bool vertical_bar_valid;
+	enum hdmi_scan_mode scan_mode;
+	enum hdmi_colorimetry colorimetry;
+	enum hdmi_picture_aspect picture_aspect;
+	enum hdmi_active_aspect active_aspect;
+	bool itc;
+	enum hdmi_extended_colorimetry extended_colorimetry;
+	enum hdmi_quantization_range quantization_range;
+	enum hdmi_nups nups;
+	unsigned char video_code;
+	enum hdmi_ycc_quantization_range ycc_quantization_range;
+	enum hdmi_content_type content_type;
+	unsigned char pixel_repeat;
+	unsigned short top_bar;
+	unsigned short bottom_bar;
+	unsigned short left_bar;
+	unsigned short right_bar;
+};
+
+int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame);
+ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer,
+				size_t size);
+
+enum hdmi_spd_sdi {
+	HDMI_SPD_SDI_UNKNOWN,
+	HDMI_SPD_SDI_DSTB,
+	HDMI_SPD_SDI_DVDP,
+	HDMI_SPD_SDI_DVHS,
+	HDMI_SPD_SDI_HDDVR,
+	HDMI_SPD_SDI_DVC,
+	HDMI_SPD_SDI_DSC,
+	HDMI_SPD_SDI_VCD,
+	HDMI_SPD_SDI_GAME,
+	HDMI_SPD_SDI_PC,
+	HDMI_SPD_SDI_BD,
+	HDMI_SPD_SDI_SACD,
+	HDMI_SPD_SDI_HDDVD,
+	HDMI_SPD_SDI_PMP,
+};
+
+struct hdmi_spd_infoframe {
+	enum hdmi_infoframe_type type;
+	unsigned char version;
+	unsigned char length;
+	char vendor[8];
+	char product[16];
+	enum hdmi_spd_sdi sdi;
+};
+
+int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame,
+			    const char *vendor, const char *product);
+ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer,
+				size_t size);
+
+enum hdmi_audio_coding_type {
+	HDMI_AUDIO_CODING_TYPE_STREAM,
+	HDMI_AUDIO_CODING_TYPE_PCM,
+	HDMI_AUDIO_CODING_TYPE_AC3,
+	HDMI_AUDIO_CODING_TYPE_MPEG1,
+	HDMI_AUDIO_CODING_TYPE_MP3,
+	HDMI_AUDIO_CODING_TYPE_MPEG2,
+	HDMI_AUDIO_CODING_TYPE_AAC_LC,
+	HDMI_AUDIO_CODING_TYPE_DTS,
+	HDMI_AUDIO_CODING_TYPE_ATRAC,
+	HDMI_AUDIO_CODING_TYPE_DSD,
+	HDMI_AUDIO_CODING_TYPE_EAC3,
+	HDMI_AUDIO_CODING_TYPE_DTS_HD,
+	HDMI_AUDIO_CODING_TYPE_MLP,
+	HDMI_AUDIO_CODING_TYPE_DST,
+	HDMI_AUDIO_CODING_TYPE_WMA_PRO,
+};
+
+enum hdmi_audio_sample_size {
+	HDMI_AUDIO_SAMPLE_SIZE_STREAM,
+	HDMI_AUDIO_SAMPLE_SIZE_16,
+	HDMI_AUDIO_SAMPLE_SIZE_20,
+	HDMI_AUDIO_SAMPLE_SIZE_24,
+};
+
+enum hdmi_audio_sample_frequency {
+	HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM,
+	HDMI_AUDIO_SAMPLE_FREQUENCY_32000,
+	HDMI_AUDIO_SAMPLE_FREQUENCY_44100,
+	HDMI_AUDIO_SAMPLE_FREQUENCY_48000,
+	HDMI_AUDIO_SAMPLE_FREQUENCY_88200,
+	HDMI_AUDIO_SAMPLE_FREQUENCY_96000,
+	HDMI_AUDIO_SAMPLE_FREQUENCY_176400,
+	HDMI_AUDIO_SAMPLE_FREQUENCY_192000,
+};
+
+enum hdmi_audio_coding_type_ext {
+	HDMI_AUDIO_CODING_TYPE_EXT_STREAM,
+	HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC,
+	HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2,
+	HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND,
+};
+
+struct hdmi_audio_infoframe {
+	enum hdmi_infoframe_type type;
+	unsigned char version;
+	unsigned char length;
+	unsigned char channels;
+	enum hdmi_audio_coding_type coding_type;
+	enum hdmi_audio_sample_size sample_size;
+	enum hdmi_audio_sample_frequency sample_frequency;
+	enum hdmi_audio_coding_type_ext coding_type_ext;
+	unsigned char channel_allocation;
+	unsigned char level_shift_value;
+	bool downmix_inhibit;
+
+};
+
+int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame);
+ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame,
+				  void *buffer, size_t size);
+
+struct hdmi_vendor_infoframe {
+	enum hdmi_infoframe_type type;
+	unsigned char version;
+	unsigned char length;
+	u8 data[27];
+};
+
+ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame,
+				   void *buffer, size_t size);
+
+#endif /* _DRM_HDMI_H */
diff --git a/include/linux/i2c/eeprom.h b/include/linux/i2c/eeprom.h
new file mode 100644
index 0000000..1393980
--- /dev/null
+++ b/include/linux/i2c/eeprom.h
@@ -0,0 +1,59 @@
+/*
+ * i2c/eeprom.h
+ *
+ * In-kernel interface for accessing eeprom memory.
+ *
+ * Copyright (C) 2012 Texas Instruments Inc.
+ *                    Pantelis Antoniou <panto@antoniou-consulting.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 I2C_EEPROM_H
+#define I2C_EEPROM_H
+
+#include <linux/types.h>
+#include <linux/memory.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+
+/*
+ * The method called in the client is
+ *
+ * int command(struct i2c_client *client, unsigned int cmd, void *arg);
+ *
+ * A single command is supported, which returns a pointer to the memory
+ * accessor already available, but which was only accessible via platform
+ * callbacks. We can't use platform callbacks anymore for device tree
+ * platforms, hence this interface.
+ *
+ */
+
+/* interface commands */
+#define I2C_EEPROM_GET_MEMORY_ACCESSOR	1
+
+static inline struct memory_accessor *
+i2c_eeprom_get_memory_accessor(struct i2c_client *client)
+{
+	int ret;
+	struct memory_accessor *macc;
+
+	/* verify that the i2c client's driver has a command method */
+	if (!client || !client->driver || !client->driver->command)
+		return ERR_PTR(-ENOTSUPP);
+
+	macc = NULL;
+	ret = client->driver->command(client, I2C_EEPROM_GET_MEMORY_ACCESSOR,
+			&macc);
+	if (ret != 0)
+		return ERR_PTR(ret);
+
+	if (macc == NULL)
+		return ERR_PTR(-ENOTSUPP);
+
+	return macc;
+}
+
+#endif
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
new file mode 100644
index 0000000..3cc8571
--- /dev/null
+++ b/include/linux/iio/common/st_sensors.h
@@ -0,0 +1,274 @@
+/*
+ * STMicroelectronics sensors library driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef ST_SENSORS_H
+#define ST_SENSORS_H
+
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/irqreturn.h>
+#include <linux/iio/trigger.h>
+
+#define ST_SENSORS_TX_MAX_LENGTH		2
+#define ST_SENSORS_RX_MAX_LENGTH		6
+
+#define ST_SENSORS_ODR_LIST_MAX			10
+#define ST_SENSORS_FULLSCALE_AVL_MAX		10
+
+#define ST_SENSORS_NUMBER_ALL_CHANNELS		4
+#define ST_SENSORS_NUMBER_DATA_CHANNELS		3
+#define ST_SENSORS_ENABLE_ALL_AXIS		0x07
+#define ST_SENSORS_BYTE_FOR_CHANNEL		2
+#define ST_SENSORS_SCAN_X			0
+#define ST_SENSORS_SCAN_Y			1
+#define ST_SENSORS_SCAN_Z			2
+#define ST_SENSORS_DEFAULT_12_REALBITS		12
+#define ST_SENSORS_DEFAULT_16_REALBITS		16
+#define ST_SENSORS_DEFAULT_POWER_ON_VALUE	0x01
+#define ST_SENSORS_DEFAULT_POWER_OFF_VALUE	0x00
+#define ST_SENSORS_DEFAULT_WAI_ADDRESS		0x0f
+#define ST_SENSORS_DEFAULT_AXIS_ADDR		0x20
+#define ST_SENSORS_DEFAULT_AXIS_MASK		0x07
+#define ST_SENSORS_DEFAULT_AXIS_N_BIT		3
+
+#define ST_SENSORS_MAX_NAME			17
+#define ST_SENSORS_MAX_4WAI			7
+
+#define ST_SENSORS_LSM_CHANNELS(device_type, index, mod, endian, bits, addr) \
+{ \
+	.type = device_type, \
+	.modified = 1, \
+	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+			IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
+	.scan_index = index, \
+	.channel2 = mod, \
+	.address = addr, \
+	.scan_type = { \
+		.sign = 's', \
+		.realbits = bits, \
+		.shift = 16 - bits, \
+		.storagebits = 16, \
+		.endianness = endian, \
+	}, \
+}
+
+#define ST_SENSOR_DEV_ATTR_SAMP_FREQ() \
+		IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, \
+			st_sensors_sysfs_get_sampling_frequency, \
+			st_sensors_sysfs_set_sampling_frequency)
+
+#define ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL() \
+		IIO_DEV_ATTR_SAMP_FREQ_AVAIL( \
+			st_sensors_sysfs_sampling_frequency_avail)
+
+#define ST_SENSORS_DEV_ATTR_SCALE_AVAIL(name) \
+		IIO_DEVICE_ATTR(name, S_IRUGO, \
+			st_sensors_sysfs_scale_avail, NULL , 0);
+
+struct st_sensor_odr_avl {
+	unsigned int hz;
+	u8 value;
+};
+
+struct st_sensor_odr {
+	u8 addr;
+	u8 mask;
+	struct st_sensor_odr_avl odr_avl[ST_SENSORS_ODR_LIST_MAX];
+};
+
+struct st_sensor_power {
+	u8 addr;
+	u8 mask;
+	u8 value_off;
+	u8 value_on;
+};
+
+struct st_sensor_axis {
+	u8 addr;
+	u8 mask;
+};
+
+struct st_sensor_fullscale_avl {
+	unsigned int num;
+	u8 value;
+	unsigned int gain;
+	unsigned int gain2;
+};
+
+struct st_sensor_fullscale {
+	u8 addr;
+	u8 mask;
+	struct st_sensor_fullscale_avl fs_avl[ST_SENSORS_FULLSCALE_AVL_MAX];
+};
+
+/**
+ * struct st_sensor_bdu - ST sensor device block data update
+ * @addr: address of the register.
+ * @mask: mask to write the block data update flag.
+ */
+struct st_sensor_bdu {
+	u8 addr;
+	u8 mask;
+};
+
+/**
+ * struct st_sensor_data_ready_irq - ST sensor device data-ready interrupt
+ * @addr: address of the register.
+ * @mask: mask to write the on/off value.
+ * struct ig1 - represents the Interrupt Generator 1 of sensors.
+ * @en_addr: address of the enable ig1 register.
+ * @en_mask: mask to write the on/off value for enable.
+ */
+struct st_sensor_data_ready_irq {
+	u8 addr;
+	u8 mask;
+	struct {
+		u8 en_addr;
+		u8 en_mask;
+	} ig1;
+};
+
+/**
+ * struct st_sensor_transfer_buffer - ST sensor device I/O buffer
+ * @buf_lock: Mutex to protect rx and tx buffers.
+ * @tx_buf: Buffer used by SPI transfer function to send data to the sensors.
+ *	This buffer is used to avoid DMA not-aligned issue.
+ * @rx_buf: Buffer used by SPI transfer to receive data from sensors.
+ *	This buffer is used to avoid DMA not-aligned issue.
+ */
+struct st_sensor_transfer_buffer {
+	struct mutex buf_lock;
+	u8 rx_buf[ST_SENSORS_RX_MAX_LENGTH];
+	u8 tx_buf[ST_SENSORS_TX_MAX_LENGTH] ____cacheline_aligned;
+};
+
+/**
+ * struct st_sensor_transfer_function - ST sensor device I/O function
+ * @read_byte: Function used to read one byte.
+ * @write_byte: Function used to write one byte.
+ * @read_multiple_byte: Function used to read multiple byte.
+ */
+struct st_sensor_transfer_function {
+	int (*read_byte) (struct st_sensor_transfer_buffer *tb,
+				struct device *dev, u8 reg_addr, u8 *res_byte);
+	int (*write_byte) (struct st_sensor_transfer_buffer *tb,
+				struct device *dev, u8 reg_addr, u8 data);
+	int (*read_multiple_byte) (struct st_sensor_transfer_buffer *tb,
+		struct device *dev, u8 reg_addr, int len, u8 *data,
+							bool multiread_bit);
+};
+
+/**
+ * struct st_sensors - ST sensors list
+ * @wai: Contents of WhoAmI register.
+ * @sensors_supported: List of supported sensors by struct itself.
+ * @ch: IIO channels for the sensor.
+ * @odr: Output data rate register and ODR list available.
+ * @pw: Power register of the sensor.
+ * @enable_axis: Enable one or more axis of the sensor.
+ * @fs: Full scale register and full scale list available.
+ * @bdu: Block data update register.
+ * @drdy_irq: Data ready register of the sensor.
+ * @multi_read_bit: Use or not particular bit for [I2C/SPI] multi-read.
+ * @bootime: samples to discard when sensor passing from power-down to power-up.
+ */
+struct st_sensors {
+	u8 wai;
+	char sensors_supported[ST_SENSORS_MAX_4WAI][ST_SENSORS_MAX_NAME];
+	struct iio_chan_spec *ch;
+	struct st_sensor_odr odr;
+	struct st_sensor_power pw;
+	struct st_sensor_axis enable_axis;
+	struct st_sensor_fullscale fs;
+	struct st_sensor_bdu bdu;
+	struct st_sensor_data_ready_irq drdy_irq;
+	bool multi_read_bit;
+	unsigned int bootime;
+};
+
+/**
+ * struct st_sensor_data - ST sensor device status
+ * @dev: Pointer to instance of struct device (I2C or SPI).
+ * @trig: The trigger in use by the core driver.
+ * @sensor: Pointer to the current sensor struct in use.
+ * @current_fullscale: Maximum range of measure by the sensor.
+ * @enabled: Status of the sensor (false->off, true->on).
+ * @multiread_bit: Use or not particular bit for [I2C/SPI] multiread.
+ * @buffer_data: Data used by buffer part.
+ * @odr: Output data rate of the sensor [Hz].
+ * @get_irq_data_ready: Function to get the IRQ used for data ready signal.
+ * @tf: Transfer function structure used by I/O operations.
+ * @tb: Transfer buffers and mutex used by I/O operations.
+ */
+struct st_sensor_data {
+	struct device *dev;
+	struct iio_trigger *trig;
+	struct st_sensors *sensor;
+	struct st_sensor_fullscale_avl *current_fullscale;
+
+	bool enabled;
+	bool multiread_bit;
+
+	char *buffer_data;
+
+	unsigned int odr;
+
+	unsigned int (*get_irq_data_ready) (struct iio_dev *indio_dev);
+
+	const struct st_sensor_transfer_function *tf;
+	struct st_sensor_transfer_buffer tb;
+};
+
+#ifdef CONFIG_IIO_BUFFER
+int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
+				const struct iio_trigger_ops *trigger_ops);
+
+void st_sensors_deallocate_trigger(struct iio_dev *indio_dev);
+
+irqreturn_t st_sensors_trigger_handler(int irq, void *p);
+
+int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf);
+#endif
+
+int st_sensors_init_sensor(struct iio_dev *indio_dev);
+
+int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable);
+
+int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable);
+
+int st_sensors_get_sampling_frequency_avl(struct iio_dev *indio_dev, char *buf);
+
+int st_sensors_get_scale_avl(struct iio_dev *indio_dev, char *buf);
+
+int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr);
+
+int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable);
+
+int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale);
+
+int st_sensors_read_info_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *ch, int *val);
+
+int st_sensors_check_device_support(struct iio_dev *indio_dev,
+			int num_sensors_list, const struct st_sensors *sensors);
+
+ssize_t st_sensors_sysfs_get_sampling_frequency(struct device *dev,
+				struct device_attribute *attr, char *buf);
+
+ssize_t st_sensors_sysfs_set_sampling_frequency(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size);
+
+ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
+				struct device_attribute *attr, char *buf);
+
+ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
+				struct device_attribute *attr, char *buf);
+
+#endif /* ST_SENSORS_H */
diff --git a/include/linux/iio/common/st_sensors_i2c.h b/include/linux/iio/common/st_sensors_i2c.h
new file mode 100644
index 0000000..67d8453
--- /dev/null
+++ b/include/linux/iio/common/st_sensors_i2c.h
@@ -0,0 +1,20 @@
+/*
+ * STMicroelectronics sensors i2c library driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef ST_SENSORS_I2C_H
+#define ST_SENSORS_I2C_H
+
+#include <linux/i2c.h>
+#include <linux/iio/common/st_sensors.h>
+
+void st_sensors_i2c_configure(struct iio_dev *indio_dev,
+		struct i2c_client *client, struct st_sensor_data *sdata);
+
+#endif /* ST_SENSORS_I2C_H */
diff --git a/include/linux/iio/common/st_sensors_spi.h b/include/linux/iio/common/st_sensors_spi.h
new file mode 100644
index 0000000..d964a35
--- /dev/null
+++ b/include/linux/iio/common/st_sensors_spi.h
@@ -0,0 +1,20 @@
+/*
+ * STMicroelectronics sensors spi library driver
+ *
+ * Copyright 2012-2013 STMicroelectronics Inc.
+ *
+ * Denis Ciocca <denis.ciocca@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef ST_SENSORS_SPI_H
+#define ST_SENSORS_SPI_H
+
+#include <linux/spi/spi.h>
+#include <linux/iio/common/st_sensors.h>
+
+void st_sensors_spi_configure(struct iio_dev *indio_dev,
+			struct spi_device *spi, struct st_sensor_data *sdata);
+
+#endif /* ST_SENSORS_SPI_H */
diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h
index 49269a2..c0bf08b 100644
--- a/include/linux/input/ti_am335x_tsc.h
+++ b/include/linux/input/ti_am335x_tsc.h
@@ -12,12 +12,24 @@
  *			A step configured to read a single
  *			co-ordinate value, can be applied
  *			more number of times for better results.
+ * @wire_config:	Different EVM's could have a different order
+ *			for connecting wires on touchscreen.
+ *			We need to provide an 8 bit number where in
+ *			the 1st four bits represent the analog lines
+ *			and the next 4 bits represent positive/
+ *			negative terminal on that input line.
+ *			Notations to represent the input lines and
+ *			terminals resoectively is as follows:
+ *			AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
+ *			XP  = 0, XN = 1, YP = 2, YN = 3.
+ *
  */
 
 struct tsc_data {
 	int wires;
 	int x_plate_resistance;
-	int steps_to_configure;
+	int coordinate_readouts;
+	int wire_config[10];
 };
 
 #endif
diff --git a/include/linux/mfd/davinci_voicecodec.h b/include/linux/mfd/davinci_voicecodec.h
index 0ab6132..7dd6524 100644
--- a/include/linux/mfd/davinci_voicecodec.h
+++ b/include/linux/mfd/davinci_voicecodec.h
@@ -26,8 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/core.h>
-
-#include <mach/edma.h>
+#include <linux/platform_data/edma.h>
 
 /*
  * Register values.
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index c79ad5d..17c0cba 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -30,8 +30,8 @@
 #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_STEPCONFIG(n)	(0x64 + ((n) * 8))
+#define REG_STEPDELAY(n)	(0x68 + ((n) * 8))
 #define REG_FIFO0CNT		0xE4
 #define REG_FIFO0THR		0xE8
 #define REG_FIFO1CNT		0xF0
@@ -46,8 +46,6 @@
 /* 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)
@@ -73,8 +71,6 @@
 #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)
@@ -96,7 +92,6 @@
 #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)
@@ -118,17 +113,29 @@
 #define CNTRLREG_8WIRE		CNTRLREG_AFE_CTRL(3)
 #define CNTRLREG_TSCENB		BIT(7)
 
+/* FIFO READ Register */
+#define FIFOREAD_DATA_MASK      (0xfff << 0)
+#define FIFOREAD_CHNLID_MASK    (0xf << 16)
+
+/* Sequencer Status */
+#define SEQ_STATUS              BIT(5)
+
 #define ADC_CLK			3000000
 #define	MAX_CLK_DIV		7
 #define TOTAL_STEPS		16
 #define TOTAL_CHANNELS		8
 
-#define TSCADC_CELLS		2
+/*
+* ADC runs at 3MHz, and it takes
+* 15 cycles to latch one data output.
+* Hence the idle time for ADC to
+* process one sample data would be
+* around 5 micro seconds.
+*/
+#define IDLE_TIMEOUT		5 /* microsec */
 
-enum tscadc_cells {
-	TSC_CELL,
-	ADC_CELL,
-};
+
+#define TSCADC_CELLS		2
 
 struct mfd_tscadc_board {
 	struct tsc_data *tsc_init;
@@ -140,7 +147,12 @@ struct ti_tscadc_dev {
 	struct regmap *regmap_tscadc;
 	void __iomem *tscadc_base;
 	int irq;
+	int used_cells;	/* 1-2 */
+	int tsc_cell;	/* -1 if not used */
+	int adc_cell;	/* -1 if not used */
 	struct mfd_cell cells[TSCADC_CELLS];
+	u32 reg_se_cache;
+	spinlock_t reg_lock;
 
 	/* tsc device */
 	struct titsc *tsc;
@@ -149,4 +161,15 @@ struct ti_tscadc_dev {
 	struct adc_device *adc;
 };
 
+static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
+{
+	struct ti_tscadc_dev **tscadc_dev = p->dev.platform_data;
+
+	return *tscadc_dev;
+}
+
+void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc);
+void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val);
+void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val);
+
 #endif
diff --git a/include/linux/mfd/tps65217.h b/include/linux/mfd/tps65217.h
index 290762f..b138fa3 100644
--- a/include/linux/mfd/tps65217.h
+++ b/include/linux/mfd/tps65217.h
@@ -21,6 +21,7 @@
 #include <linux/i2c.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/input.h>
 
 /* TPS chip id list */
 #define TPS65217			0xF0
@@ -274,6 +275,11 @@ struct tps65217 {
 	struct regulator_dev *rdev[TPS65217_NUM_REGULATOR];
 	struct tps_info *info[TPS65217_NUM_REGULATOR];
 	struct regmap *regmap;
+
+	/* Power button and IRQ handling */
+	int irq_gpio;	/* might not be set */
+	int irq;
+	struct input_dev *pwr_but;
 };
 
 static inline struct tps65217 *dev_to_tps65217(struct device *dev)
diff --git a/include/linux/of.h b/include/linux/of.h
index 5ebcc5c..6c72d94 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -23,6 +23,7 @@
 #include <linux/spinlock.h>
 #include <linux/topology.h>
 #include <linux/notifier.h>
+#include <linux/i2c.h>
 
 #include <asm/byteorder.h>
 #include <asm/errno.h>
@@ -114,6 +115,26 @@ static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
 	set_bit(flag, &n->_flags);
 }
 
+static inline void of_node_clear_flag(struct device_node *n, unsigned long flag)
+{
+	clear_bit(flag, &n->_flags);
+}
+
+static inline int of_property_check_flag(struct property *p, unsigned long flag)
+{
+	return test_bit(flag, &p->_flags);
+}
+
+static inline void of_property_set_flag(struct property *p, unsigned long flag)
+{
+	set_bit(flag, &p->_flags);
+}
+
+static inline void of_property_clear_flag(struct property *p, unsigned long flag)
+{
+	clear_bit(flag, &p->_flags);
+}
+
 extern struct device_node *of_find_all_nodes(struct device_node *prev);
 
 /*
@@ -278,6 +299,46 @@ extern int of_parse_phandle_with_args(const struct device_node *np,
 	const char *list_name, const char *cells_name, int index,
 	struct of_phandle_args *out_args);
 
+#if defined(CONFIG_OF_DYNAMIC)
+extern int of_property_notify(int action, struct device_node *np,
+			      struct property *prop);
+#else
+static inline int of_property_notify(int action, struct device_node *np,
+			      struct property *prop)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PROC_DEVICETREE
+
+extern void of_add_proc_dt_entry(struct device_node *dn);
+extern void of_remove_proc_dt_entry(struct device_node *dn);
+
+extern void of_add_proc_dt_prop_entry(struct device_node *np,
+		struct property *prop);
+
+extern void of_remove_proc_dt_prop_entry(struct device_node *np,
+		struct property *prop);
+
+extern void of_update_proc_dt_prop_entry(struct device_node *np,
+		struct property *newprop, struct property *oldprop);
+#else
+
+static inline void of_add_proc_dt_entry(struct device_node *dn) { }
+static inline void of_remove_proc_dt_entry(struct device_node *dn) { }
+
+static inline void of_add_proc_dt_prop_entry(struct device_node *np,
+		struct property *prop) { }
+
+static inline void of_remove_proc_dt_prop_entry(struct device_node *np,
+		struct property *prop) { }
+
+static inline void of_update_proc_dt_prop_entry(struct device_node *np,
+		struct property *newprop, struct property *oldprop) { }
+
+#endif
+
 extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
 extern int of_alias_get_id(struct device_node *np, const char *stem);
 
@@ -531,4 +592,192 @@ static inline int of_property_read_u32(const struct device_node *np,
 	return of_property_read_u32_array(np, propname, out_value, 1);
 }
 
+/**
+ * General utilities for working with live trees.
+ *
+ * All functions with two leading underscores operate
+ * without taking node references, so you either have to
+ * own the devtree lock or work on detached trees only.
+ */
+
+#ifdef CONFIG_OF
+
+/* iterator for internal use; not references, neither affects devtree lock */
+#define __for_each_child_of_node(dn, chld) \
+	for (chld = (dn)->child; chld != NULL; chld = chld->sibling)
+
+void __of_free_property(struct property *prop);
+void __of_free_tree(struct device_node *node);
+struct property *__of_copy_property(const struct property *prop, gfp_t flags);
+struct device_node *__of_create_empty_node( const char *name,
+		const char *type, const char *full_name,
+		phandle phandle, gfp_t flags);
+struct device_node *__of_find_node_by_full_name(struct device_node *node,
+		const char *full_name);
+int of_multi_prop_cmp(const struct property *prop, const char *value);
+
+#else /* !CONFIG_OF */
+
+#define __for_each_child_of_node(dn, chld) \
+	while (0)
+
+static inline void __of_free_property(struct property *prop) { }
+
+static inline void __of_free_tree(struct device_node *node) { }
+
+static inline struct property *__of_copy_property(const struct property *prop,
+		gfp_t flags)
+{
+	return NULL;
+}
+
+static inline struct device_node *__of_create_empty_node( const char *name,
+		const char *type, const char *full_name,
+		phandle phandle, gfp_t flags)
+{
+	return NULL;
+}
+
+static inline struct device_node *__of_find_node_by_full_name(struct device_node *node,
+		const char *full_name)
+{
+	return NULL;
+}
+
+static inline int of_multi_prop_cmp(const struct property *prop, const char *value)
+{
+	return -1;
+}
+
+#endif	/* !CONFIG_OF */
+
+
+/* illegal phandle value (set when unresolved) */
+#define OF_PHANDLE_ILLEGAL	0xdeadbeef
+
+#ifdef CONFIG_OF_RESOLVE
+
+int of_resolve(struct device_node *resolve);
+
+#else
+
+static inline int of_resolve(struct device_node *resolve)
+{
+	return -ENOTSUPP;
+}
+
+#endif
+
+/**
+ * Overlay support
+ */
+
+/**
+ * struct of_overlay_log_entry	- Holds a DT log entry
+ * @node:	list_head for the log list
+ * @action:	notifier action
+ * @np:		pointer to the device node affected
+ * @prop:	pointer to the property affected
+ * @old_prop:	hold a pointer to the original property
+ *
+ * Every modification of the device tree during application of the
+ * overlay is held in a list of of_overlay_log_entry structures.
+ * That way we can recover from a partial application, or we can
+ * revert the overlay properly.
+ */
+struct of_overlay_log_entry {
+	struct list_head node;
+	unsigned long action;
+	struct device_node *np;
+	struct property *prop;
+	struct property *old_prop;
+};
+
+/**
+ * struct of_overlay_device_entry	- Holds an overlay device entry
+ * @node:	list_head for the device list
+ * @np:		device node pointer to the device node affected
+ * @pdev:	pointer to the platform device affected
+ * @client:	pointer to the I2C client device affected
+ * @state:	new device state
+ * @prevstate:	previous device state
+ *
+ * When the overlay results in a device node's state to change this
+ * fact is recorded in a list of device entries. After the overlay
+ * is applied we can create/destroy the platform devices according
+ * to the new state of the live tree.
+ */
+struct of_overlay_device_entry {
+	struct list_head node;
+	struct device_node *np;
+	struct platform_device *pdev;
+	struct i2c_client *client;
+	int prevstate;
+	int state;
+};
+
+/**
+ * struct of_overlay_info	- Holds a single overlay info
+ * @target:	target of the overlay operation
+ * @overlay:	pointer to the overlay contents node
+ * @lock:	Lock to hold when accessing the lists
+ * @le_list:	List of the overlay logs
+ * @de_list:	List of the overlay records
+ * @notifier:	of reconfiguration notifier
+ *
+ * Holds a single overlay state, including all the overlay logs &
+ * records.
+ */
+struct of_overlay_info {
+	struct device_node *target;
+	struct device_node *overlay;
+	struct mutex lock;
+	struct list_head le_list;
+	struct list_head de_list;
+	struct notifier_block notifier;
+	int device_depth;
+};
+
+#ifdef CONFIG_OF_OVERLAY
+
+int of_overlay(int count, struct of_overlay_info *ovinfo_tab);
+int of_overlay_revert(int count, struct of_overlay_info *ovinfo_tab);
+
+int of_fill_overlay_info(struct device_node *info_node,
+		struct of_overlay_info *ovinfo);
+int of_build_overlay_info(struct device_node *tree,
+		int *cntp, struct of_overlay_info **ovinfop);
+int of_free_overlay_info(int cnt, struct of_overlay_info *ovinfo);
+
+#else
+
+static inline int of_overlay(int count, struct of_overlay_info *ovinfo_tab)
+{
+	return -ENOTSUPP;
+}
+
+static inline int of_overlay_revert(int count, struct of_overlay_info *ovinfo_tab)
+{
+	return -ENOTSUPP;
+}
+
+static inline int of_fill_overlay_info(struct device_node *info_node,
+		struct of_overlay_info *ovinfo)
+{
+	return -ENOTSUPP;
+}
+
+static inline int of_build_overlay_info(struct device_node *tree,
+		int *cntp, struct of_overlay_info **ovinfop)
+{
+	return -ENOTSUPP;
+}
+
+int of_free_overlay_info(int cnt, struct of_overlay_info *ovinfo)
+{
+	return -ENOTSUPP;
+}
+
+#endif
+
 #endif /* _LINUX_OF_H */
diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h
new file mode 100644
index 0000000..67158dd
--- /dev/null
+++ b/include/linux/of_dma.h
@@ -0,0 +1,72 @@
+/*
+ * 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;
+};
+
+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 void 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 void 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/of_i2c.h b/include/linux/of_i2c.h
index cfb545c..53fca8f 100644
--- a/include/linux/of_i2c.h
+++ b/include/linux/of_i2c.h
@@ -15,6 +15,9 @@
 #if defined(CONFIG_OF_I2C) || defined(CONFIG_OF_I2C_MODULE)
 #include <linux/i2c.h>
 
+struct i2c_client *
+of_i2c_register_device(struct i2c_adapter *adap, struct device_node *node);
+
 extern void of_i2c_register_devices(struct i2c_adapter *adap);
 
 /* must call put_device() when done with returned i2c_client device */
@@ -25,6 +28,14 @@ extern struct i2c_adapter *of_find_i2c_adapter_by_node(
 						struct device_node *node);
 
 #else
+
+static inline struct i2c_client *
+of_i2c_register_device(struct i2c_adapter *adap,
+		struct device_node *node)
+{
+	return ERR_PTR(-ENODEV);
+}
+
 static inline void of_i2c_register_devices(struct i2c_adapter *adap)
 {
 	return;
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index 24368a2..be5b27e 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -35,6 +35,7 @@ struct cpsw_platform_data {
 	u32	bd_ram_size;  /*buffer descriptor ram size */
 	u32	rx_descs;	/* Number of Rx Descriptios */
 	u32	mac_control;	/* Mac control register */
+	int	disable_napi;	/* disable NAPI */
 };
 
 #endif /* __CPSW_H__ */
diff --git a/include/linux/platform_data/edma.h b/include/linux/platform_data/edma.h
new file mode 100644
index 0000000..ffc1fb2
--- /dev/null
+++ b/include/linux/platform_data/edma.h
@@ -0,0 +1,183 @@
+/*
+ *  TI EDMA definitions
+ *
+ *  Copyright (C) 2006-2013 Texas Instruments.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+/*
+ * This EDMA3 programming framework exposes two basic kinds of resource:
+ *
+ *  Channel	Triggers transfers, usually from a hardware event but
+ *		also manually or by "chaining" from DMA completions.
+ *		Each channel is coupled to a Parameter RAM (PaRAM) slot.
+ *
+ *  Slot	Each PaRAM slot holds a DMA transfer descriptor (PaRAM
+ *		"set"), source and destination addresses, a link to a
+ *		next PaRAM slot (if any), options for the transfer, and
+ *		instructions for updating those addresses.  There are
+ *		more than twice as many slots as event channels.
+ *
+ * Each PaRAM set describes a sequence of transfers, either for one large
+ * buffer or for several discontiguous smaller buffers.  An EDMA transfer
+ * is driven only from a channel, which performs the transfers specified
+ * in its PaRAM slot until there are no more transfers.  When that last
+ * transfer completes, the "link" field may be used to reload the channel's
+ * PaRAM slot with a new transfer descriptor.
+ *
+ * The EDMA Channel Controller (CC) maps requests from channels into physical
+ * Transfer Controller (TC) requests when the channel triggers (by hardware
+ * or software events, or by chaining).  The two physical DMA channels provided
+ * by the TCs are thus shared by many logical channels.
+ *
+ * DaVinci hardware also has a "QDMA" mechanism which is not currently
+ * supported through this interface.  (DSP firmware uses it though.)
+ */
+
+#ifndef EDMA_H_
+#define EDMA_H_
+
+/* PaRAM slots are laid out like this */
+struct edmacc_param {
+	unsigned int opt;
+	unsigned int src;
+	unsigned int a_b_cnt;
+	unsigned int dst;
+	unsigned int src_dst_bidx;
+	unsigned int link_bcntrld;
+	unsigned int src_dst_cidx;
+	unsigned int ccnt;
+};
+
+/* fields in edmacc_param.opt */
+#define SAM		BIT(0)
+#define DAM		BIT(1)
+#define SYNCDIM		BIT(2)
+#define STATIC		BIT(3)
+#define EDMA_FWID	(0x07 << 8)
+#define TCCMODE		BIT(11)
+#define EDMA_TCC(t)	((t) << 12)
+#define TCINTEN		BIT(20)
+#define ITCINTEN	BIT(21)
+#define TCCHEN		BIT(22)
+#define ITCCHEN		BIT(23)
+
+/*ch_status paramater of callback function possible values*/
+#define DMA_COMPLETE 1
+#define DMA_CC_ERROR 2
+#define DMA_TC1_ERROR 3
+#define DMA_TC2_ERROR 4
+
+enum address_mode {
+	INCR = 0,
+	FIFO = 1
+};
+
+enum fifo_width {
+	W8BIT = 0,
+	W16BIT = 1,
+	W32BIT = 2,
+	W64BIT = 3,
+	W128BIT = 4,
+	W256BIT = 5
+};
+
+enum dma_event_q {
+	EVENTQ_0 = 0,
+	EVENTQ_1 = 1,
+	EVENTQ_2 = 2,
+	EVENTQ_3 = 3,
+	EVENTQ_DEFAULT = -1
+};
+
+enum sync_dimension {
+	ASYNC = 0,
+	ABSYNC = 1
+};
+
+#define EDMA_CTLR_CHAN(ctlr, chan)	(((ctlr) << 16) | (chan))
+#define EDMA_CTLR(i)			((i) >> 16)
+#define EDMA_CHAN_SLOT(i)		((i) & 0xffff)
+
+#define EDMA_CHANNEL_ANY		-1	/* for edma_alloc_channel() */
+#define EDMA_SLOT_ANY			-1	/* for edma_alloc_slot() */
+#define EDMA_CONT_PARAMS_ANY		 1001
+#define EDMA_CONT_PARAMS_FIXED_EXACT	 1002
+#define EDMA_CONT_PARAMS_FIXED_NOT_EXACT 1003
+
+#define EDMA_MAX_CC               2
+
+/* alloc/free DMA channels and their dedicated parameter RAM slots */
+int edma_alloc_channel(int channel,
+	void (*callback)(unsigned channel, u16 ch_status, void *data),
+	void *data, enum dma_event_q);
+void edma_free_channel(unsigned channel);
+
+/* alloc/free parameter RAM slots */
+int edma_alloc_slot(unsigned ctlr, int slot);
+void edma_free_slot(unsigned slot);
+
+/* alloc/free a set of contiguous parameter RAM slots */
+int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count);
+int edma_free_cont_slots(unsigned slot, int count);
+
+/* calls that operate on part of a parameter RAM slot */
+void edma_set_src(unsigned slot, dma_addr_t src_port,
+				enum address_mode mode, enum fifo_width);
+void edma_set_dest(unsigned slot, dma_addr_t dest_port,
+				 enum address_mode mode, enum fifo_width);
+void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst);
+void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx);
+void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx);
+void edma_set_transfer_params(unsigned slot, u16 acnt, u16 bcnt, u16 ccnt,
+		u16 bcnt_rld, enum sync_dimension sync_mode);
+void edma_link(unsigned from, unsigned to);
+void edma_unlink(unsigned from);
+
+/* calls that operate on an entire parameter RAM slot */
+void edma_write_slot(unsigned slot, const struct edmacc_param *params);
+void edma_read_slot(unsigned slot, struct edmacc_param *params);
+
+/* channel control operations */
+int edma_start(unsigned channel);
+void edma_stop(unsigned channel);
+void edma_clean_channel(unsigned channel);
+void edma_clear_event(unsigned channel);
+void edma_pause(unsigned channel);
+void edma_resume(unsigned channel);
+
+struct edma_rsv_info {
+
+	const s16	(*rsv_chans)[2];
+	const s16	(*rsv_slots)[2];
+};
+
+/* platform_data for EDMA driver */
+struct edma_soc_info {
+
+	/* how many dma resources of each type */
+	unsigned	n_channel;
+	unsigned	n_region;
+	unsigned	n_slot;
+	unsigned	n_tc;
+	unsigned	n_cc;
+	/*
+	 * Default queue is expected to be a low-priority queue.
+	 * This way, long transfers on the default queue started
+	 * by the codec engine will not cause audio defects.
+	 */
+	enum dma_event_q	default_queue;
+
+	/* Resource reservation for other cores */
+	struct edma_rsv_info	*rsv;
+
+	const s8	(*queue_tc_mapping)[2];
+	const s8	(*queue_priority_mapping)[2];
+	const s16	(*xbar_chans)[2];
+};
+
+#endif
diff --git a/include/linux/platform_data/invensense_mpu6050.h b/include/linux/platform_data/invensense_mpu6050.h
new file mode 100644
index 0000000..ad3aa7b
--- /dev/null
+++ b/include/linux/platform_data/invensense_mpu6050.h
@@ -0,0 +1,31 @@
+/*
+* Copyright (C) 2012 Invensense, 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 __INV_MPU6050_PLATFORM_H_
+#define __INV_MPU6050_PLATFORM_H_
+
+/**
+ * struct inv_mpu6050_platform_data - Platform data for the mpu driver
+ * @orientation:	Orientation matrix of the chip
+ *
+ * Contains platform specific information on how to configure the MPU6050 to
+ * work on this platform.  The orientation matricies are 3x3 rotation matricies
+ * that are applied to the data to rotate from the mounting orientation to the
+ * platform orientation.  The values must be one of 0, 1, or -1 and each row and
+ * column should have exactly 1 non-zero value.
+ */
+struct inv_mpu6050_platform_data {
+	__s8 orientation[9];
+};
+
+#endif
diff --git a/include/linux/platform_data/mmc-davinci.h b/include/linux/platform_data/mmc-davinci.h
index 5ba6b22..6910209 100644
--- a/include/linux/platform_data/mmc-davinci.h
+++ b/include/linux/platform_data/mmc-davinci.h
@@ -25,9 +25,6 @@ struct davinci_mmc_config {
 
 	/* Version of the MMC/SD controller */
 	u8	version;
-
-	/* Number of sg segments */
-	u8	nr_sg;
 };
 void davinci_setup_mmc(int module, struct davinci_mmc_config *config);
 
diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h
index 2bf1b30..d548994 100644
--- a/include/linux/platform_data/mmc-omap.h
+++ b/include/linux/platform_data/mmc-omap.h
@@ -115,6 +115,9 @@ struct omap_mmc_platform_data {
 
 		int switch_pin;			/* gpio (card detect) */
 		int gpio_wp;			/* gpio (write protect) */
+		int gpio_reset;			/* gpio (reset) */
+		int gpio_reset_active_low;	/* 1 if reset is active low */
+		u32 gpio_reset_hold_us;		/* time to hold in us */
 
 		int (*set_bus_mode)(struct device *dev, int slot, int bus_mode);
 		int (*set_power)(struct device *dev, int slot,
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index 24d32ca..6bf9ef4 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -60,6 +60,8 @@ struct omap_nand_platform_data {
 	int			devsize;
 	enum omap_ecc           ecc_opt;
 	struct gpmc_nand_regs	reg;
-};
 
+	/* for passing the partitions */
+	struct device_node	*of_node;
+};
 #endif
diff --git a/include/linux/platform_data/mtd-onenand-omap2.h b/include/linux/platform_data/mtd-onenand-omap2.h
index 685af7e..e9a9fb1 100644
--- a/include/linux/platform_data/mtd-onenand-omap2.h
+++ b/include/linux/platform_data/mtd-onenand-omap2.h
@@ -29,5 +29,8 @@ struct omap_onenand_platform_data {
 	u8			flags;
 	u8			regulator_can_sleep;
 	u8			skip_initial_unlocking;
+
+	/* for passing the partitions */
+	struct device_node	*of_node;
 };
 #endif
diff --git a/include/linux/platform_data/spi-davinci.h b/include/linux/platform_data/spi-davinci.h
index 7af305b..8dc2fa47 100644
--- a/include/linux/platform_data/spi-davinci.h
+++ b/include/linux/platform_data/spi-davinci.h
@@ -19,7 +19,7 @@
 #ifndef __ARCH_ARM_DAVINCI_SPI_H
 #define __ARCH_ARM_DAVINCI_SPI_H
 
-#include <mach/edma.h>
+#include <linux/platform_data/edma.h>
 
 #define SPI_INTERN_CS	0xFF
 
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index a9ded9a..e48c2d5 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -293,4 +293,8 @@ extern int platform_pm_restore(struct device *dev);
 #define USE_PLATFORM_PM_SLEEP_OPS
 #endif
 
+/* helper functions for resource list managment */
+int platform_device_unlink_resources(struct platform_device *pdev);
+int platform_device_link_resources(struct platform_device *pdev);
+
 #endif /* _PLATFORM_DEVICE_H_ */
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index 6d661f3..9165922 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -4,10 +4,27 @@
 #include <linux/err.h>
 #include <linux/of.h>
 
+#define MAX_PWMS 1024
+
 struct pwm_device;
 struct seq_file;
 
 #if IS_ENABLED(CONFIG_PWM) || IS_ENABLED(CONFIG_HAVE_PWM)
+
+/*
+ * "valid" PWM numbers are nonnegative and may be passed to
+ * setup routines like pwm_get().  only some valid numbers
+ * can successfully be requested and used.
+ *
+ * Invalid PWM numbers are useful for indicating no-such-PWM in
+ * platform data and other tables.
+ */
+
+static inline bool pwm_is_valid(int number)
+{
+	return number >= 0 && number < MAX_PWMS;
+}
+
 /*
  * pwm_request - request a PWM device
  */
@@ -75,7 +92,8 @@ enum pwm_polarity {
 
 enum {
 	PWMF_REQUESTED = 1 << 0,
-	PWMF_ENABLED = 1 << 1,
+	PWMF_ENABLED = 1 << 1, /* set running via /sys/class/pwm/pwmX/run */
+	PWMF_EXPORT = 1 << 2, /* exported via /sys/class/pwm/export */
 };
 
 struct pwm_device {
@@ -87,6 +105,10 @@ struct pwm_device {
 	void			*chip_data;
 
 	unsigned int		period; /* in nanoseconds */
+#ifdef CONFIG_PWM_SYSFS
+	unsigned int		duty; /* in nanoseconds */
+	enum pwm_polarity	polarity;
+#endif
 };
 
 static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period)
@@ -159,6 +181,9 @@ struct pwm_chip {
 	struct pwm_device *	(*of_xlate)(struct pwm_chip *pc,
 					    const struct of_phandle_args *args);
 	unsigned int		of_pwm_n_cells;
+#ifdef CONFIG_PWM_SYSFS
+	unsigned		exported:1;
+#endif
 };
 
 #if IS_ENABLED(CONFIG_PWM)
@@ -174,6 +199,7 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
 struct pwm_device *of_pwm_xlate_with_flags(struct pwm_chip *pc,
 		const struct of_phandle_args *args);
 
+struct pwm_device *of_pwm_request(struct device_node *np, const char *consumer);
 struct pwm_device *pwm_get(struct device *dev, const char *consumer);
 void pwm_put(struct pwm_device *pwm);
 
@@ -207,6 +233,12 @@ static inline struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
 	return ERR_PTR(-ENODEV);
 }
 
+static inline struct pwm_device *of_pwm_request(struct device_node *np,
+					 const char *consumer)
+{
+	return ERR_PTR(-ENODEV);
+}
+
 static inline struct pwm_device *pwm_get(struct device *dev,
 					 const char *consumer)
 {
diff --git a/include/linux/rstctl.h b/include/linux/rstctl.h
new file mode 100644
index 0000000..b2e674a
--- /dev/null
+++ b/include/linux/rstctl.h
@@ -0,0 +1,71 @@
+/*
+ * Reset control subsystem
+ *
+ * Copyright (C) 2013 Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef __LINUX_RSTCTL_H
+#define __LINUX_RSTCTL_H
+
+#include <linux/of.h>
+#include <linux/list.h>
+
+struct rstctl_dev;
+
+struct rstctl_line {
+	const char *name;
+	void *data;
+};
+
+struct rstctl_ops {
+	int (*request)(struct rstctl_dev *rdev,
+			const struct rstctl_line *line);
+	int (*release)(struct rstctl_dev *rdev,
+			const struct rstctl_line *line);
+	int (*assert)(struct rstctl_dev *rdev,
+			const struct rstctl_line *line);
+	int (*deassert)(struct rstctl_dev *rdev,
+			const struct rstctl_line *line);
+	int (*pulse)(struct rstctl_dev *rdev,
+			const struct rstctl_line *line,
+			unsigned long hold_ns);
+	struct module *owner;
+};
+
+struct rstctl_desc {
+	const char *name;
+	const struct rstctl_ops *ops;
+	int nlines;
+	const struct rstctl_line *lines;
+};
+
+struct rstctl_dev {
+	struct list_head node;
+	struct device *dev;
+	const struct rstctl_desc *rdesc;
+	struct list_head handles;
+};
+
+struct rstctl {
+	struct list_head node;		/* linked all in */
+	struct device *dev; 		/* the user */
+	struct rstctl_dev *rdev;	/* the controler */
+	const struct rstctl_line *line;
+	const char *label;
+};
+
+/* driver API */
+struct rstctl_dev *rstctl_register(struct device *dev,
+		const struct rstctl_desc *rdesc);
+int rstctl_unregister(struct rstctl_dev *rdev);
+
+/* consumer API */
+struct rstctl *rstctl_get(struct device *dev, const char *id);
+void rstctl_put(struct rstctl *rctrl);
+
+int rstctl_assert(struct rstctl *rctrl);
+int rstctl_deassert(struct rstctl *rctrl);
+int rstctl_pulse(struct rstctl *rctrl, unsigned long hold_ns);
+
+#endif
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
index eb50525..053c268 100644
--- a/include/linux/usb/musb.h
+++ b/include/linux/usb/musb.h
@@ -99,6 +99,8 @@ struct musb_hdrc_platform_data {
 	/* MUSB_HOST, MUSB_PERIPHERAL, or MUSB_OTG */
 	u8		mode;
 
+	u8		has_mailbox:1;
+
 	/* for clk_get() */
 	const char	*clock;
 
diff --git a/include/linux/usb/omap_control_usb.h b/include/linux/usb/omap_control_usb.h
new file mode 100644
index 0000000..fbc7407
--- /dev/null
+++ b/include/linux/usb/omap_control_usb.h
@@ -0,0 +1,73 @@
+/*
+ * omap_control_usb.h - Header file for the USB part of control module.
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@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 __OMAP_CONTROL_USB_H__
+#define __OMAP_CONTROL_USB_H__
+
+struct omap_control_usb {
+	struct device *dev;
+
+	u32 __iomem *dev_conf;
+	u32 __iomem *otghs_control;
+
+	u8 has_mailbox:1;
+};
+
+struct omap_control_usb_platform_data {
+	u8 has_mailbox:1;
+};
+
+#define	PHY_PD		BIT(0)
+
+#define	AVALID		BIT(0)
+#define	BVALID		BIT(1)
+#define	VBUSVALID	BIT(2)
+#define	SESSEND		BIT(3)
+#define	IDDIG		BIT(4)
+
+#if (defined(CONFIG_OMAP_CONTROL_USB) || \
+				defined(CONFIG_OMAP_CONTROL_USB_MODULE))
+extern struct device *get_omap_control_dev(void);
+extern void omap_control_usb_phy_power(struct device *dev, int on);
+extern void omap_control_usb_host_mode(struct device *dev);
+extern void omap_control_usb_device_mode(struct device *dev);
+extern void omap_control_usb_set_sessionend(struct device *dev);
+#else
+static inline struct device *get_omap_control_dev()
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline void omap_control_usb_phy_power(struct device *dev, int on)
+{
+}
+
+static inline void omap_control_usb_host_mode(struct device *dev)
+{
+}
+
+static inline void omap_control_usb_device_mode(struct device *dev)
+{
+}
+
+static inline void omap_control_usb_set_sessionend(struct device *dev)
+{
+}
+#endif
+
+#endif	/* __OMAP_CONTROL_USB_H__ */
diff --git a/include/linux/usb/omap_usb.h b/include/linux/usb/omap_usb.h
index 0ea17f8..3db9b53 100644
--- a/include/linux/usb/omap_usb.h
+++ b/include/linux/usb/omap_usb.h
@@ -25,13 +25,11 @@ struct omap_usb {
 	struct usb_phy		phy;
 	struct phy_companion	*comparator;
 	struct device		*dev;
-	u32 __iomem		*control_dev;
+	struct device		*control_dev;
 	struct clk		*wkupclk;
 	u8			is_suspended:1;
 };
 
-#define	PHY_PD	0x1
-
 #define	phy_to_omapusb(x)	container_of((x), struct omap_usb, phy)
 
 #if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE)
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
index a29ae1e..c7f5a98 100644
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
@@ -106,9 +106,25 @@ struct usb_phy {
 			enum usb_device_speed speed);
 };
 
+/**
+ * struct usb_phy_bind - represent the binding for the phy
+ * @dev_name: the device name of the device that will bind to the phy
+ * @phy_dev_name: the device name of the phy
+ * @index: used if a single controller uses multiple phys
+ * @phy: reference to the phy
+ * @list: to maintain a linked list of the binding information
+ */
+struct usb_phy_bind {
+	const char	*dev_name;
+	const char	*phy_dev_name;
+	u8		index;
+	struct usb_phy	*phy;
+	struct list_head list;
+};
 
 /* for board-specific init logic */
 extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type);
+extern int usb_add_phy_dev(struct usb_phy *);
 extern void usb_remove_phy(struct usb_phy *);
 
 /* helpers for direct access thru low-level io interface */
@@ -149,8 +165,14 @@ usb_phy_shutdown(struct usb_phy *x)
 extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
 extern struct usb_phy *devm_usb_get_phy(struct device *dev,
 	enum usb_phy_type type);
+extern struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index);
+extern struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index);
+extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
+	const char *phandle, u8 index);
 extern void usb_put_phy(struct usb_phy *);
 extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
+extern struct usb_phy_bind *usb_bind_phy(const char *dev_name, u8 index,
+				const char *phy_dev_name);
 #else
 static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
 {
@@ -163,6 +185,22 @@ static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
 	return NULL;
 }
 
+static inline struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
+{
+	return NULL;
+}
+
+static inline struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
+{
+	return NULL;
+}
+
+static inline struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
+	const char *phandle, u8 index)
+{
+	return NULL;
+}
+
 static inline void usb_put_phy(struct usb_phy *x)
 {
 }
@@ -171,6 +209,11 @@ static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x)
 {
 }
 
+static inline struct usb_phy_bind *usb_bind_phy(const char *dev_name, u8 index,
+				const char *phy_dev_name)
+{
+	return NULL;
+}
 #endif
 
 static inline int
diff --git a/include/media/mt9t112.h b/include/media/mt9t112.h
index a43c74a..bab2746 100644
--- a/include/media/mt9t112.h
+++ b/include/media/mt9t112.h
@@ -13,6 +13,8 @@
 
 #define MT9T112_FLAG_PCLK_RISING_EDGE	(1 << 0)
 #define MT9T112_FLAG_DATAWIDTH_8	(1 << 1) /* default width is 10 */
+#define MT9T112_FLAG_VFLIP             (1 << 2)
+#define MT9T112_FLAG_HFLIP             (1 << 3)
 
 struct mt9t112_pll_divider {
 	u8 m, n;
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index c019b24..7ae8823 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -223,4 +223,7 @@
 /* ARC (Synopsys) on-chip UART */
 #define PORT_ARC       101
 
+/* JHD629 pseudo port */
+#define PORT_JHD629    102
+
 #endif /* _UAPILINUX_SERIAL_CORE_H */
diff --git a/include/video/display_timing.h b/include/video/display_timing.h
new file mode 100644
index 0000000..71e9a38
--- /dev/null
+++ b/include/video/display_timing.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * description of display timings
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_DISPLAY_TIMING_H
+#define __LINUX_DISPLAY_TIMING_H
+
+#include <linux/bitops.h>
+#include <linux/types.h>
+
+/* VESA display monitor timing parameters */
+#define VESA_DMT_HSYNC_LOW		BIT(0)
+#define VESA_DMT_HSYNC_HIGH		BIT(1)
+#define VESA_DMT_VSYNC_LOW		BIT(2)
+#define VESA_DMT_VSYNC_HIGH		BIT(3)
+
+/* display specific flags */
+#define DISPLAY_FLAGS_DE_LOW		BIT(0)	/* data enable flag */
+#define DISPLAY_FLAGS_DE_HIGH		BIT(1)
+#define DISPLAY_FLAGS_PIXDATA_POSEDGE	BIT(2)	/* drive data on pos. edge */
+#define DISPLAY_FLAGS_PIXDATA_NEGEDGE	BIT(3)	/* drive data on neg. edge */
+#define DISPLAY_FLAGS_INTERLACED	BIT(4)
+#define DISPLAY_FLAGS_DOUBLESCAN	BIT(5)
+
+/*
+ * A single signal can be specified via a range of minimal and maximal values
+ * with a typical value, that lies somewhere inbetween.
+ */
+struct timing_entry {
+	u32 min;
+	u32 typ;
+	u32 max;
+};
+
+enum timing_entry_index {
+	TE_MIN = 0,
+	TE_TYP = 1,
+	TE_MAX = 2,
+};
+
+/*
+ * Single "mode" entry. This describes one set of signal timings a display can
+ * have in one setting. This struct can later be converted to struct videomode
+ * (see include/video/videomode.h). As each timing_entry can be defined as a
+ * range, one struct display_timing may become multiple struct videomodes.
+ *
+ * Example: hsync active high, vsync active low
+ *
+ *				    Active Video
+ * Video  ______________________XXXXXXXXXXXXXXXXXXXXXX_____________________
+ *	  |<- sync ->|<- back ->|<----- active ----->|<- front ->|<- sync..
+ *	  |	     |	 porch  |		     |	 porch	 |
+ *
+ * HSync _|¯¯¯¯¯¯¯¯¯¯|___________________________________________|¯¯¯¯¯¯¯¯¯
+ *
+ * VSync ¯|__________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_________
+ */
+struct display_timing {
+	struct timing_entry pixelclock;
+
+	struct timing_entry hactive;		/* hor. active video */
+	struct timing_entry hfront_porch;	/* hor. front porch */
+	struct timing_entry hback_porch;	/* hor. back porch */
+	struct timing_entry hsync_len;		/* hor. sync len */
+
+	struct timing_entry vactive;		/* ver. active video */
+	struct timing_entry vfront_porch;	/* ver. front porch */
+	struct timing_entry vback_porch;	/* ver. back porch */
+	struct timing_entry vsync_len;		/* ver. sync len */
+
+	unsigned int dmt_flags;			/* VESA DMT flags */
+	unsigned int data_flags;		/* video data flags */
+};
+
+/*
+ * This describes all timing settings a display provides.
+ * The native_mode is the default setting for this display.
+ * Drivers that can handle multiple videomodes should work with this struct and
+ * convert each entry to the desired end result.
+ */
+struct display_timings {
+	unsigned int num_timings;
+	unsigned int native_mode;
+
+	struct display_timing **timings;
+};
+
+/* get value specified by index from struct timing_entry */
+static inline u32 display_timing_get_value(const struct timing_entry *te,
+					   enum timing_entry_index index)
+{
+	switch (index) {
+	case TE_MIN:
+		return te->min;
+		break;
+	case TE_TYP:
+		return te->typ;
+		break;
+	case TE_MAX:
+		return te->max;
+		break;
+	default:
+		return te->typ;
+	}
+}
+
+/* get one entry from struct display_timings */
+static inline struct display_timing *display_timings_get(const struct
+							 display_timings *disp,
+							 unsigned int index)
+{
+	if (disp->num_timings > index)
+		return disp->timings[index];
+	else
+		return NULL;
+}
+
+void display_timings_release(struct display_timings *disp);
+
+#endif
diff --git a/include/video/of_display_timing.h b/include/video/of_display_timing.h
new file mode 100644
index 0000000..8016eb7
--- /dev/null
+++ b/include/video/of_display_timing.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * display timings of helpers
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_OF_DISPLAY_TIMING_H
+#define __LINUX_OF_DISPLAY_TIMING_H
+
+struct device_node;
+struct display_timings;
+
+#define OF_USE_NATIVE_MODE -1
+
+struct display_timings *of_get_display_timings(struct device_node *np);
+int of_display_timings_exist(struct device_node *np);
+
+#endif
diff --git a/include/video/of_videomode.h b/include/video/of_videomode.h
new file mode 100644
index 0000000..a07efcc
--- /dev/null
+++ b/include/video/of_videomode.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * videomode of-helpers
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_OF_VIDEOMODE_H
+#define __LINUX_OF_VIDEOMODE_H
+
+struct device_node;
+struct videomode;
+
+int of_get_videomode(struct device_node *np, struct videomode *vm,
+		     int index);
+
+#endif /* __LINUX_OF_VIDEOMODE_H */
diff --git a/include/video/videomode.h b/include/video/videomode.h
new file mode 100644
index 0000000..a421562
--- /dev/null
+++ b/include/video/videomode.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * generic videomode description
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_VIDEOMODE_H
+#define __LINUX_VIDEOMODE_H
+
+#include <linux/types.h>
+#include <video/display_timing.h>
+
+/*
+ * Subsystem independent description of a videomode.
+ * Can be generated from struct display_timing.
+ */
+struct videomode {
+	unsigned long pixelclock;	/* pixelclock in Hz */
+
+	u32 hactive;
+	u32 hfront_porch;
+	u32 hback_porch;
+	u32 hsync_len;
+
+	u32 vactive;
+	u32 vfront_porch;
+	u32 vback_porch;
+	u32 vsync_len;
+
+	unsigned int dmt_flags;	/* VESA DMT flags */
+	unsigned int data_flags; /* video data flags */
+};
+
+/**
+ * videomode_from_timing - convert display timing to videomode
+ * @disp: structure with all possible timing entries
+ * @vm: return value
+ * @index: index into the list of display timings in devicetree
+ *
+ * DESCRIPTION:
+ * This function converts a struct display_timing to a struct videomode.
+ */
+int videomode_from_timing(const struct display_timings *disp,
+			  struct videomode *vm, unsigned int index);
+
+#endif
diff --git a/kernel/printk.c b/kernel/printk.c
index 267ce78..0ca8ffe 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1756,6 +1756,13 @@ static int __init console_setup(char *str)
 	char *s, *options, *brl_options = NULL;
 	int idx;
 
+#ifdef CONFIG_SERIAL_OMAP
+	if (!strncmp(str, "tty0", 4) && '0' <= str[4] && '9' >= str[4]) {
+		str[3] = 'O';
+		pr_warn("We are opening your eyes, assuming you want to use an OMAP based serial driver and not a zeroMAP based one! ;)\n");
+		pr_warn("Which means 'tty0%s' was changed to 'ttyO%s' automagically for your pleasure.\n", str+4, str+4);
+	}
+#endif
 #ifdef CONFIG_A11Y_BRAILLE_CONSOLE
 	if (!memcmp(str, "brl,", 4)) {
 		brl_options = "";
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 76c3d0a..e1b4580 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -104,6 +104,7 @@ static const u8 lowpan_llprefix[] = {0xfe, 0x80};
 struct lowpan_dev_info {
 	struct net_device	*real_dev; /* real WPAN device ptr */
 	struct mutex		dev_list_mtx; /* mutex for list ops */
+	unsigned short		fragment_tag;
 };
 
 struct lowpan_dev_record {
@@ -120,7 +121,6 @@ struct lowpan_fragment {
 	struct list_head	list;		/* fragments list */
 };
 
-static unsigned short fragment_tag;
 static LIST_HEAD(lowpan_fragments);
 static DEFINE_SPINLOCK(flist_lock);
 
@@ -284,6 +284,9 @@ lowpan_compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb)
 	/* checksum is always inline */
 	memcpy(*hc06_ptr, &uh->check, 2);
 	*hc06_ptr += 2;
+
+	/* skip the UDP header */
+	skb_pull(skb, sizeof(struct udphdr));
 }
 
 static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
@@ -309,9 +312,8 @@ static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
 }
 
 static int
-lowpan_uncompress_udp_header(struct sk_buff *skb)
+lowpan_uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
 {
-	struct udphdr *uh = udp_hdr(skb);
 	u8 tmp;
 
 	if (!uh)
@@ -358,6 +360,14 @@ lowpan_uncompress_udp_header(struct sk_buff *skb)
 		/* copy checksum */
 		memcpy(&uh->check, &skb->data[0], 2);
 		skb_pull(skb, 2);
+
+		/*
+		 * UDP lenght needs to be infered from the lower layers
+		 * here, we obtain the hint from the remaining size of the
+		 * frame
+		 */
+		uh->len = htons(skb->len + sizeof(struct udphdr));
+		pr_debug("uncompressed UDP length: src = %d", uh->len);
 	} else {
 		pr_debug("ERROR: unsupported NH format\n");
 		goto err;
@@ -377,17 +387,14 @@ static int lowpan_header_create(struct sk_buff *skb,
 	struct ipv6hdr *hdr;
 	const u8 *saddr = _saddr;
 	const u8 *daddr = _daddr;
-	u8 *head;
+	u8 head[100];
 	struct ieee802154_addr sa, da;
 
+	/* TODO:
+	 * if this package isn't ipv6 one, where should it be routed?
+	 */
 	if (type != ETH_P_IPV6)
 		return 0;
-		/* TODO:
-		 * if this package isn't ipv6 one, where should it be routed?
-		 */
-	head = kzalloc(100, GFP_KERNEL);
-	if (head == NULL)
-		return -ENOMEM;
 
 	hdr = ipv6_hdr(skb);
 	hc06_ptr = head + 2;
@@ -561,8 +568,6 @@ static int lowpan_header_create(struct sk_buff *skb,
 	skb_pull(skb, sizeof(struct ipv6hdr));
 	memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head);
 
-	kfree(head);
-
 	lowpan_raw_dump_table(__func__, "raw skb data dump", skb->data,
 				skb->len);
 
@@ -577,27 +582,63 @@ static int lowpan_header_create(struct sk_buff *skb,
 	 * this isn't implemented in mainline yet, so currently we assign 0xff
 	 */
 	{
+		mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
+		mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
+
 		/* prepare wpan address data */
 		sa.addr_type = IEEE802154_ADDR_LONG;
-		sa.pan_id = 0xff;
+		sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
 
-		da.addr_type = IEEE802154_ADDR_LONG;
-		da.pan_id = 0xff;
-
-		memcpy(&(da.hwaddr), daddr, 8);
 		memcpy(&(sa.hwaddr), saddr, 8);
+		/* intra-PAN communications */
+		da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
 
-		mac_cb(skb)->flags = IEEE802154_FC_TYPE_DATA;
+		/*
+		 * if the destination address is the broadcast address, use the
+		 * corresponding short address
+		 */
+		if (lowpan_is_addr_broadcast(daddr)) {
+			da.addr_type = IEEE802154_ADDR_SHORT;
+			da.short_addr = IEEE802154_ADDR_BROADCAST;
+		} else {
+			da.addr_type = IEEE802154_ADDR_LONG;
+			memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN);
+
+			/* request acknowledgment */
+			mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
+		}
 
 		return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev,
 				type, (void *)&da, (void *)&sa, skb->len);
 	}
 }
 
+static int lowpan_give_skb_to_devices(struct sk_buff *skb)
+{
+	struct lowpan_dev_record *entry;
+	struct sk_buff *skb_cp;
+	int stat = NET_RX_SUCCESS;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(entry, &lowpan_devices, list)
+		if (lowpan_dev_info(entry->ldev)->real_dev == skb->dev) {
+			skb_cp = skb_copy(skb, GFP_ATOMIC);
+			if (!skb_cp) {
+				stat = -ENOMEM;
+				break;
+			}
+
+			skb_cp->dev = entry->ldev;
+			stat = netif_rx(skb_cp);
+		}
+	rcu_read_unlock();
+
+	return stat;
+}
+
 static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
 {
 	struct sk_buff *new;
-	struct lowpan_dev_record *entry;
 	int stat = NET_RX_SUCCESS;
 
 	new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb),
@@ -614,19 +655,7 @@ static int lowpan_skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr)
 	new->protocol = htons(ETH_P_IPV6);
 	new->pkt_type = PACKET_HOST;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(entry, &lowpan_devices, list)
-		if (lowpan_dev_info(entry->ldev)->real_dev == new->dev) {
-			skb = skb_copy(new, GFP_ATOMIC);
-			if (!skb) {
-				stat = -ENOMEM;
-				break;
-			}
-
-			skb->dev = entry->ldev;
-			stat = netif_rx(skb);
-		}
-	rcu_read_unlock();
+	stat = lowpan_give_skb_to_devices(new);
 
 	kfree_skb(new);
 
@@ -645,7 +674,7 @@ static void lowpan_fragment_timer_expired(unsigned long entry_addr)
 }
 
 static struct lowpan_fragment *
-lowpan_alloc_new_frame(struct sk_buff *skb, u8 len, u16 tag)
+lowpan_alloc_new_frame(struct sk_buff *skb, u16 len, u16 tag)
 {
 	struct lowpan_fragment *frame;
 
@@ -715,7 +744,7 @@ lowpan_process_data(struct sk_buff *skb)
 	{
 		struct lowpan_fragment *frame;
 		/* slen stores the rightmost 8 bits of the 11 bits length */
-		u8 slen, offset;
+		u8 slen, offset = 0;
 		u16 len, tag;
 		bool found = false;
 
@@ -726,6 +755,18 @@ lowpan_process_data(struct sk_buff *skb)
 		/* adds the 3 MSB to the 8 LSB to retrieve the 11 bits length */
 		len = ((iphc0 & 7) << 8) | slen;
 
+		if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1) {
+			pr_debug("%s received a FRAG1 packet (tag: %d, "
+				 "size of the entire IP packet: %d)",
+				 __func__, tag, len);
+		} else { /* FRAGN */
+			if (lowpan_fetch_skb_u8(skb, &offset))
+				goto unlock_and_drop;
+			pr_debug("%s received a FRAGN packet (tag: %d, "
+				 "size of the entire IP packet: %d, "
+				 "offset: %d)", __func__, tag, len, offset * 8);
+		}
+
 		/*
 		 * check if frame assembling with the same tag is
 		 * already in progress
@@ -740,17 +781,13 @@ lowpan_process_data(struct sk_buff *skb)
 
 		/* alloc new frame structure */
 		if (!found) {
+			pr_debug("%s first fragment received for tag %d, "
+				 "begin packet reassembly", __func__, tag);
 			frame = lowpan_alloc_new_frame(skb, len, tag);
 			if (!frame)
 				goto unlock_and_drop;
 		}
 
-		if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1)
-			goto unlock_and_drop;
-
-		if (lowpan_fetch_skb_u8(skb, &offset)) /* fetch offset */
-			goto unlock_and_drop;
-
 		/* if payload fits buffer, copy it */
 		if (likely((offset * 8 + skb->len) <= frame->length))
 			skb_copy_to_linear_data_offset(frame->skb, offset * 8,
@@ -768,6 +805,9 @@ lowpan_process_data(struct sk_buff *skb)
 			list_del(&frame->list);
 			spin_unlock_bh(&flist_lock);
 
+			pr_debug("%s successfully reassembled fragment "
+				 "(tag %d)", __func__, tag);
+
 			dev_kfree_skb(skb);
 			skb = frame->skb;
 			kfree(frame);
@@ -913,10 +953,35 @@ lowpan_process_data(struct sk_buff *skb)
 	}
 
 	/* UDP data uncompression */
-	if (iphc0 & LOWPAN_IPHC_NH_C)
-		if (lowpan_uncompress_udp_header(skb))
+	if (iphc0 & LOWPAN_IPHC_NH_C) {
+		struct udphdr uh;
+		struct sk_buff *new;
+		if (lowpan_uncompress_udp_header(skb, &uh))
 			goto drop;
 
+		/*
+		 * replace the compressed UDP head by the uncompressed UDP
+		 * header
+		 */
+		new = skb_copy_expand(skb, sizeof(struct udphdr),
+				      skb_tailroom(skb), GFP_ATOMIC);
+		kfree_skb(skb);
+
+		if (!new)
+			return -ENOMEM;
+
+		skb = new;
+
+		skb_push(skb, sizeof(struct udphdr));
+		skb_reset_transport_header(skb);
+		skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
+
+		lowpan_raw_dump_table(__func__, "raw UDP header dump",
+				      (u8 *)&uh, sizeof(uh));
+
+		hdr.nexthdr = UIP_PROTO_UDP;
+	}
+
 	/* Not fragmented package */
 	hdr.payload_len = htons(skb->len);
 
@@ -964,13 +1029,13 @@ static int lowpan_get_mac_header_length(struct sk_buff *skb)
 
 static int
 lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
-			int mlen, int plen, int offset)
+			int mlen, int plen, int offset, int type)
 {
 	struct sk_buff *frag;
 	int hlen, ret;
 
-	/* if payload length is zero, therefore it's a first fragment */
-	hlen = (plen == 0 ? LOWPAN_FRAG1_HEAD_SIZE :  LOWPAN_FRAGN_HEAD_SIZE);
+	hlen = (type == LOWPAN_DISPATCH_FRAG1) ?
+			LOWPAN_FRAG1_HEAD_SIZE : LOWPAN_FRAGN_HEAD_SIZE;
 
 	lowpan_raw_dump_inline(__func__, "6lowpan fragment header", head, hlen);
 
@@ -998,14 +1063,14 @@ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head,
 }
 
 static int
-lowpan_skb_fragmentation(struct sk_buff *skb)
+lowpan_skb_fragmentation(struct sk_buff *skb, struct net_device *dev)
 {
 	int  err, header_length, payload_length, tag, offset = 0;
 	u8 head[5];
 
 	header_length = lowpan_get_mac_header_length(skb);
 	payload_length = skb->len - header_length;
-	tag = fragment_tag++;
+	tag = lowpan_dev_info(dev)->fragment_tag++;
 
 	/* first fragment header */
 	head[0] = LOWPAN_DISPATCH_FRAG1 | ((payload_length >> 8) & 0x7);
@@ -1013,7 +1078,16 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
 	head[2] = tag >> 8;
 	head[3] = tag & 0xff;
 
-	err = lowpan_fragment_xmit(skb, head, header_length, 0, 0);
+	err = lowpan_fragment_xmit(skb, head, header_length, LOWPAN_FRAG_SIZE,
+				   0, LOWPAN_DISPATCH_FRAG1);
+
+	if (err) {
+		pr_debug("%s unable to send FRAG1 packet (tag: %d)",
+			 __func__, tag);
+		goto exit;
+	}
+
+	offset = LOWPAN_FRAG_SIZE;
 
 	/* next fragment header */
 	head[0] &= ~LOWPAN_DISPATCH_FRAG1;
@@ -1028,10 +1102,17 @@ lowpan_skb_fragmentation(struct sk_buff *skb)
 			len = payload_length - offset;
 
 		err = lowpan_fragment_xmit(skb, head, header_length,
-							len, offset);
+					   len, offset, LOWPAN_DISPATCH_FRAGN);
+		if (err) {
+			pr_debug("%s unable to send a subsequent FRAGN packet "
+				 "(tag: %d, offset: %d", __func__, tag, offset);
+			goto exit;
+		}
+
 		offset += len;
 	}
 
+exit:
 	return err;
 }
 
@@ -1054,7 +1135,7 @@ static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	pr_debug("frame is too big, fragmentation is needed\n");
-	err = lowpan_skb_fragmentation(skb);
+	err = lowpan_skb_fragmentation(skb, dev);
 error:
 	dev_kfree_skb(skb);
 out:
@@ -1082,6 +1163,12 @@ static u16 lowpan_get_short_addr(const struct net_device *dev)
 	return ieee802154_mlme_ops(real_dev)->get_short_addr(real_dev);
 }
 
+static u8 lowpan_get_dsn(const struct net_device *dev)
+{
+	struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
+	return ieee802154_mlme_ops(real_dev)->get_dsn(real_dev);
+}
+
 static struct header_ops lowpan_header_ops = {
 	.create	= lowpan_header_create,
 };
@@ -1095,6 +1182,7 @@ static struct ieee802154_mlme_ops lowpan_mlme = {
 	.get_pan_id = lowpan_get_pan_id,
 	.get_phy = lowpan_get_phy,
 	.get_short_addr = lowpan_get_short_addr,
+	.get_dsn = lowpan_get_dsn,
 };
 
 static void lowpan_setup(struct net_device *dev)
@@ -1137,19 +1225,42 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 		goto drop;
 
 	/* check that it's our buffer */
-	switch (skb->data[0] & 0xe0) {
-	case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
-	case LOWPAN_DISPATCH_FRAG1:	/* first fragment header */
-	case LOWPAN_DISPATCH_FRAGN:	/* next fragments headers */
-		local_skb = skb_clone(skb, GFP_ATOMIC);
+	if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
+		/* Copy the packet so that the IPv6 header is
+		 * properly aligned.
+		 */
+		local_skb = skb_copy_expand(skb, NET_SKB_PAD - 1,
+					    skb_tailroom(skb), GFP_ATOMIC);
 		if (!local_skb)
 			goto drop;
-		lowpan_process_data(local_skb);
 
+		local_skb->protocol = htons(ETH_P_IPV6);
+		local_skb->pkt_type = PACKET_HOST;
+
+		/* Pull off the 1-byte of 6lowpan header. */
+		skb_pull(local_skb, 1);
+		skb_reset_network_header(local_skb);
+		skb_set_transport_header(local_skb, sizeof(struct ipv6hdr));
+
+		lowpan_give_skb_to_devices(local_skb);
+
+		kfree_skb(local_skb);
 		kfree_skb(skb);
-		break;
-	default:
-		break;
+	} else {
+		switch (skb->data[0] & 0xe0) {
+		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
+		case LOWPAN_DISPATCH_FRAG1:	/* first fragment header */
+		case LOWPAN_DISPATCH_FRAGN:	/* next fragments headers */
+			local_skb = skb_clone(skb, GFP_ATOMIC);
+			if (!local_skb)
+				goto drop;
+			lowpan_process_data(local_skb);
+
+			kfree_skb(skb);
+			break;
+		default:
+			break;
+		}
 	}
 
 	return NET_RX_SUCCESS;
@@ -1175,6 +1286,7 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev,
 		return -ENODEV;
 
 	lowpan_dev_info(dev)->real_dev = real_dev;
+	lowpan_dev_info(dev)->fragment_tag = 0;
 	mutex_init(&lowpan_dev_info(dev)->dev_list_mtx);
 
 	entry = kzalloc(sizeof(struct lowpan_dev_record), GFP_KERNEL);
diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h
index bba5f83..4b8f917 100644
--- a/net/ieee802154/6lowpan.h
+++ b/net/ieee802154/6lowpan.h
@@ -92,9 +92,10 @@
  */
 #define lowpan_is_iid_16_bit_compressable(a)	\
 	((((a)->s6_addr16[4]) == 0) &&		\
-	 (((a)->s6_addr16[5]) == 0) &&		\
-	 (((a)->s6_addr16[6]) == 0) &&		\
-	 ((((a)->s6_addr[14]) & 0x80) == 0))
+	 (((a)->s6_addr[10]) == 0) &&		\
+	 (((a)->s6_addr[11]) == 0xff) &&	\
+	 (((a)->s6_addr[12]) == 0xfe) &&	\
+	 (((a)->s6_addr[13]) == 0))
 
 /* multicast address */
 #define is_addr_mcast(a) (((a)->s6_addr[0]) == 0xFF)
diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h
index a4dcaf1..21fa386 100644
--- a/net/mac802154/mac802154.h
+++ b/net/mac802154/mac802154.h
@@ -114,5 +114,6 @@ void mac802154_dev_set_ieee_addr(struct net_device *dev);
 u16 mac802154_dev_get_pan_id(const struct net_device *dev);
 void mac802154_dev_set_pan_id(struct net_device *dev, u16 val);
 void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
+u8 mac802154_dev_get_dsn(const struct net_device *dev);
 
 #endif /* MAC802154_H */
diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c
index d8d2770..a99910d 100644
--- a/net/mac802154/mac_cmd.c
+++ b/net/mac802154/mac_cmd.c
@@ -73,4 +73,5 @@ struct ieee802154_mlme_ops mac802154_mlme_wpan = {
 	.start_req = mac802154_mlme_start_req,
 	.get_pan_id = mac802154_dev_get_pan_id,
 	.get_short_addr = mac802154_dev_get_short_addr,
+	.get_dsn = mac802154_dev_get_dsn,
 };
diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c
index f47781a..f03e55f 100644
--- a/net/mac802154/mib.c
+++ b/net/mac802154/mib.c
@@ -159,6 +159,15 @@ void mac802154_dev_set_pan_id(struct net_device *dev, u16 val)
 	}
 }
 
+u8 mac802154_dev_get_dsn(const struct net_device *dev)
+{
+	struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+	BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+	return priv->dsn++;
+}
+
 static void phy_chan_notify(struct work_struct *work)
 {
 	struct phy_chan_notify_work *nw = container_of(work,
diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
index 199b922..7d3f659 100644
--- a/net/mac802154/wpan.c
+++ b/net/mac802154/wpan.c
@@ -41,7 +41,7 @@ static inline int mac802154_fetch_skb_u8(struct sk_buff *skb, u8 *val)
 		return -EINVAL;
 
 	*val = skb->data[0];
-	 skb_pull(skb, 1);
+	skb_pull(skb, 1);
 
 	return 0;
 }
@@ -137,18 +137,16 @@ static int mac802154_header_create(struct sk_buff *skb,
 	struct ieee802154_addr dev_addr;
 	struct mac802154_sub_if_data *priv = netdev_priv(dev);
 	int pos = 2;
-	u8 *head;
+	u8 head[MAC802154_FRAME_HARD_HEADER_LEN];
 	u16 fc;
 
 	if (!daddr)
 		return -EINVAL;
 
-	head = kzalloc(MAC802154_FRAME_HARD_HEADER_LEN, GFP_KERNEL);
-	if (head == NULL)
-		return -ENOMEM;
-
 	head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */
 	fc = mac_cb_type(skb);
+	if (mac_cb_is_ackreq(skb))
+		fc |= IEEE802154_FC_ACK_REQ;
 
 	if (!saddr) {
 		spin_lock_bh(&priv->mib_lock);
@@ -210,7 +208,6 @@ static int mac802154_header_create(struct sk_buff *skb,
 	head[1] = fc >> 8;
 
 	memcpy(skb_push(skb, pos), head, pos);
-	kfree(head);
 
 	return pos;
 }
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index a2fc3a0..c5861b8 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -1,17 +1,799 @@
-#
-# This file is a placeholder to prevent accidental build breakage if someone
-# enables CONFIG_CFG80211_INTERNAL_REGDB.  Almost no one actually needs to
-# enable that build option.
-#
-# You should be using CRDA instead.  It is even better if you use the CRDA
-# package provided by your distribution, since they will probably keep it
-# up-to-date on your behalf.
-#
-# If you _really_ intend to use CONFIG_CFG80211_INTERNAL_REGDB then you will
-# need to replace this file with one containing appropriately formatted
-# regulatory rules that cover the regulatory domains you will be using.  Your
-# best option is to extract the db.txt file from the wireless-regdb git
-# repository:
-#
-#   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git
-#
+# This is the world regulatory domain
+country 00:
+	(2402 - 2472 @ 40), (3, 20)
+	# Channel 12 - 13.
+	(2457 - 2482 @ 40), (3, 20), PASSIVE-SCAN, NO-IBSS
+	# Channel 14. Only JP enables this and for 802.11b only
+	(2474 - 2494 @ 20), (3, 20), PASSIVE-SCAN, NO-IBSS, NO-OFDM
+	# Channel 36 - 48
+	(5170 - 5250 @ 40), (3, 20), PASSIVE-SCAN, NO-IBSS
+	# NB: 5260 MHz - 5700 MHz requies DFS
+	# Channel 149 - 165
+	(5735 - 5835 @ 40), (3, 20), PASSIVE-SCAN, NO-IBSS
+
+
+country AD:
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country AE:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+
+country AL:
+	(2402 - 2482 @ 20), (N/A, 20)
+
+country AM:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 20), (N/A, 18)
+	(5250 - 5330 @ 20), (N/A, 18), DFS
+
+country AN:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+
+country AR:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country AT: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country AU:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 23)
+	(5250 - 5330 @ 40), (3, 23), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country AW:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+
+country AZ:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 18)
+	(5250 - 5330 @ 40), (N/A, 18), DFS
+
+country BA: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country BB:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 23)
+	(5250 - 5330 @ 40), (3, 23), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country BD:
+	(2402 - 2482 @ 40), (N/A, 20)
+
+country BE: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country BG: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 23)
+	(5250 - 5290 @ 40), (N/A, 23), DFS
+	(5490 - 5710 @ 40), (N/A, 30), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country BH:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 20), (N/A, 20)
+	(5250 - 5330 @ 20), (N/A, 20), DFS
+	(5735 - 5835 @ 20), (N/A, 20)
+
+country BL:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 18)
+	(5250 - 5330 @ 40), (N/A, 18), DFS
+
+country BN:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country BO:
+	(2402 - 2482 @ 40), (N/A, 30)
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country BR:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country BY:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+
+country BZ:
+	(2402 - 2482 @ 40), (N/A, 30)
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country CA:
+	(2402 - 2472 @ 40), (3, 27)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country CH: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country CL:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5735 - 5835 @ 40), (N/A, 20)
+
+country CN:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5735 - 5835 @ 40), (N/A, 30)
+	# 60 gHz band channels 1,4: 28dBm, channels 2,3: 44dBm
+	# ref: http://www.miit.gov.cn/n11293472/n11505629/n11506593/n11960250/n11960606/n11960700/n12330791.files/n12330790.pdf
+	(57240 - 59400 @ 2160), (N/A, 28)
+	(59400 - 63720 @ 2160), (N/A, 44)
+	(63720 - 65880 @ 2160), (N/A, 28)
+
+country CO:
+	(2402 - 2472 @ 40), (3, 27)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 23), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country CR:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 20), (3, 17)
+	(5250 - 5330 @ 20), (3, 23), DFS
+	(5735 - 5835 @ 20), (3, 30)
+
+country CS:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+
+country CY: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+# Data from http://www.ctu.eu/164/download/VOR/VOR-12-08-2005-34.pdf
+# and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf
+# Power at 5250 - 5350 MHz and 5470 - 5725 MHz can be doubled if TPC is
+# implemented.
+country CZ: DFS-ETSI
+	(2400 - 2483.5 @ 40), (N/A, 100 mW)
+	(5150 - 5250 @ 40), (N/A, 200 mW), NO-OUTDOOR
+	(5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
+	(5470 - 5725 @ 40), (N/A, 500 mW), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+# Data from "Frequenznutzungsplan" (as published in April 2008), downloaded from
+# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38448/publicationFile/2659/Frequenznutzungsplan2008_Id17448pdf.pdf
+# For the 5GHz range also see
+# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38216/publicationFile/6579/WLAN5GHzVfg7_2010_28042010pdf.pdf
+# The values have been reduced by a factor of 2 (3db) for non TPC devices
+# (in other words: devices with TPC can use twice the tx power of this table).
+# Note that the docs do not require TPC for 5150--5250; the reduction to
+# 100mW thus is not strictly required -- however the conservative 100mW
+# limit is used here as the non-interference with radar and satellite
+# apps relies on the attenuation by the building walls only in the
+# absence of DFS; the neighbour countries have 100mW limit here as well.
+
+country DE: DFS-ETSI
+	# entries 279004 and 280006
+	(2400 - 2483.5 @ 40), (N/A, 100 mW)
+	# entry 303005
+	(5150 - 5250 @ 40), (N/A, 100 mW), NO-OUTDOOR
+	# entries 304002 and 305002
+	(5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
+	# entries 308002, 309001 and 310003
+	(5470 - 5725 @ 40), (N/A, 500 mW), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country DK: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country DO:
+	(2402 - 2472 @ 40), (3, 27)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 23), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country DZ:
+	(2402 - 2482 @ 40), (N/A, 20)
+
+country EC:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 20), (3, 17)
+	(5250 - 5330 @ 20), (3, 23), DFS
+	(5735 - 5835 @ 20), (3, 30)
+
+country EE: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country EG:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 20), (N/A, 20)
+	(5250 - 5330 @ 20), (N/A, 20), DFS
+
+country ES: DFS-ETSI
+	(2400 - 2483.5 @ 40), (N/A, 100 mW)
+	(5150 - 5250 @ 40), (N/A, 100 mW), NO-OUTDOOR
+	(5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
+	(5470 - 5725 @ 40), (N/A, 500 mW), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country FI: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country FR: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country GE:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 18)
+	(5250 - 5330 @ 40), (N/A, 18), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country GB: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country GD:
+	(2402 - 2472 @ 40), (3, 27)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country GR: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country GL: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 20), (N/A, 20)
+	(5250 - 5330 @ 20), (N/A, 20), DFS
+	(5490 - 5710 @ 20), (N/A, 27), DFS
+
+country GT:
+	(2402 - 2472 @ 40), (3, 27)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 23), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country GU:
+	(2402 - 2472 @ 40), (3, 27)
+	(5170 - 5250 @ 20), (3, 17)
+	(5250 - 5330 @ 20), (3, 23), DFS
+	(5735 - 5835 @ 20), (3, 30)
+
+country HN:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country HK:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country HR: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country HT:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+
+country HU: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country ID:
+	(2402 - 2482 @ 40), (N/A, 20)
+
+country IE: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country IL:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5150 - 5250 @ 40), (N/A, 200 mW), NO-OUTDOOR
+	(5250 - 5350 @ 40), (N/A, 200 mW), NO-OUTDOOR, DFS
+
+country IN:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5735 - 5835 @ 40), (N/A, 20)
+
+country IS: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country IR:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country IT: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country JM:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country JP:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(2474 - 2494 @ 20), (N/A, 20), NO-OFDM
+	(4910 - 4990 @ 40), (N/A, 23)
+	(5030 - 5090 @ 40), (N/A, 23)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 23), DFS
+
+country JO:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 18)
+
+country KE:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country KH:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+
+country KP:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5330 @ 40), (3, 20)
+	(5160 - 5250 @ 40), (3, 20), DFS
+	(5490 - 5630 @ 40), (3, 30), DFS
+	(5735 - 5815 @ 40), (3, 30)
+
+country KR:
+	(2402 - 2482 @ 20), (N/A, 20)
+	(5170 - 5250 @ 20), (3, 20)
+	(5250 - 5330 @ 20), (3, 20), DFS
+	(5490 - 5630 @ 20), (3, 30), DFS
+	(5735 - 5815 @ 20), (3, 30)
+
+country KW:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+
+country KZ:
+	(2402 - 2482 @ 40), (N/A, 20)
+
+country LB:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country LI: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+
+country LK:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 20), (3, 17)
+	(5250 - 5330 @ 20), (3, 20), DFS
+	(5490 - 5710 @ 20), (3, 20), DFS
+	(5735 - 5835 @ 20), (3, 30)
+
+country LT: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country LU: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country LV: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country MC: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 18)
+	(5250 - 5330 @ 40), (N/A, 18), DFS
+
+country MA:
+	(2402 - 2482 @ 40), (N/A, 20)
+
+country MO:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 23)
+	(5250 - 5330 @ 40), (3, 23), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country MK: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country MT: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country MY:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 30), DFS
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country MX:
+	(2402 - 2472 @ 40), (3, 27)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 23), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country NL: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20), NO-OUTDOOR
+	(5250 - 5330 @ 40), (N/A, 20), NO-OUTDOOR, DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country NO: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country NP:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country NZ:
+	(2402 - 2482 @ 40), (N/A, 30)
+	(5170 - 5250 @ 20), (3, 23)
+	(5250 - 5330 @ 20), (3, 23), DFS
+	(5735 - 5835 @ 20), (3, 30)
+
+country OM:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country PA:
+	(2402 - 2472 @ 40), (3, 27)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 23), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country PE:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country PG:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 23), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country PH:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country PK:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country PL: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country PT: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country PR:
+	(2402 - 2472 @ 40), (3, 27)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 23), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country QA:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country RO: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+
+# Source:
+# http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf
+country RS:
+	(2400 - 2483.5 @ 40), (N/A, 100 mW)
+	(5150 - 5350 @ 40), (N/A, 200 mW), NO-OUTDOOR
+	(5470 - 5725 @ 20), (3, 1000 mW), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country RU:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5735 - 5835 @ 20), (N/A, 30)
+
+country RW:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5735 - 5835 @ 40), (N/A, 30)
+
+country SA:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 20), (3, 23)
+	(5250 - 5330 @ 20), (3, 23), DFS
+	(5735 - 5835 @ 20), (3, 30)
+
+country SE: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country SG:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5735 - 5835 @ 40), (N/A, 20)
+
+country SI: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country SK: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+	(5490 - 5710 @ 40), (N/A, 27), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country SV:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 20), (3, 17)
+	(5250 - 5330 @ 20), (3, 23), DFS
+	(5735 - 5835 @ 20), (3, 30)
+
+country SY:
+	(2402 - 2482 @ 40), (N/A, 20)
+
+country TW:
+	(2402 - 2472 @ 40), (3, 27)
+	(5270 - 5330 @ 40), (3, 17), DFS
+	(5735 - 5815 @ 40), (3, 30)
+
+country TH:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country TT:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country TN:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 20), (N/A, 20)
+	(5250 - 5330 @ 20), (N/A, 20), DFS
+
+country TR: DFS-ETSI
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 20), (N/A, 20)
+	(5250 - 5330 @ 20), (N/A, 20), DFS
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+ 
+# Source:
+# #914 / 06 Sep 2007: http://www.ucrf.gov.ua/uk/doc/nkrz/1196068874
+# #1174 / 23 Oct 2008: http://www.nkrz.gov.ua/uk/activities/ruling/1225269361
+# (appendix 8)
+# Listed 5GHz range is a lowest common denominator for all related
+# rules in the referenced laws. Such a range is used because of
+# disputable definitions there.
+country UA:
+	(2400 - 2483.5 @ 40), (N/A, 20), NO-OUTDOOR
+	(5150 - 5350 @ 40), (N/A, 20), NO-OUTDOOR
+	# 60 gHz band channels 1-4, ref: Etsi En 302 567
+	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+country US: DFS-FCC
+	(2402 - 2472 @ 40), (3, 27)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5600 @ 40), (3, 20), DFS
+	(5650 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+	# 60g band
+	# reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255
+	# channels 1,2,3, EIRP=40dBm(43dBm peak)
+	(57240 - 63720 @ 2160), (N/A, 40)
+
+country UY:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country UZ:
+	(2402 - 2472 @ 40), (3, 27)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country VE:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5735 - 5815 @ 40), (N/A, 23)
+
+country VN:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (N/A, 20)
+	(5250 - 5330 @ 40), (N/A, 20), DFS
+
+country YE:
+	(2402 - 2482 @ 40), (N/A, 20)
+
+country ZA:
+	(2402 - 2482 @ 40), (N/A, 20)
+	(5170 - 5250 @ 40), (3, 17)
+	(5250 - 5330 @ 40), (3, 20), DFS
+	(5490 - 5710 @ 40), (3, 20), DFS
+	(5735 - 5835 @ 40), (3, 30)
+
+country ZW:
+	(2402 - 2482 @ 40), (N/A, 20)
+
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index bdf42fd..72ac3eb 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -269,6 +269,10 @@ cmd_dtc = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -d $(depfile
 $(obj)/%.dtb: $(src)/%.dts FORCE
 	$(call if_changed_dep,dtc)
 
+# plugin compile
+quiet_cmd_dtco = DTCO    $@
+cmd_dtco = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -@ -d $(depfile) $<
+
 # Bzip2
 # ---------------------------------------------------------------------------
 
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index ee96a25..970c0a3 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -457,22 +457,93 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
 				     struct node *node, struct property *prop)
 {
 	struct marker *m = prop->val.markers;
+	struct fixup *f, **fp;
+	struct fixup_entry *fe, **fep;
 	struct node *refnode;
 	cell_t phandle;
+	int has_phandle_refs;
+
+	has_phandle_refs = 0;
+	for_each_marker_of_type(m, REF_PHANDLE) {
+		has_phandle_refs = 1;
+		break;
+	}
+
+	if (!has_phandle_refs)
+		return;
 
 	for_each_marker_of_type(m, REF_PHANDLE) {
 		assert(m->offset + sizeof(cell_t) <= prop->val.len);
 
 		refnode = get_node_by_ref(dt, m->ref);
-		if (! refnode) {
+		if (!refnode && !symbol_fixup_support) {
 			FAIL(c, "Reference to non-existent node or label \"%s\"\n",
-			     m->ref);
+				m->ref);
 			continue;
 		}
 
-		phandle = get_node_phandle(dt, refnode);
-		*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
+		if (!refnode) {
+			/* allocate fixup entry */
+			fe = xmalloc(sizeof(*fe));
+
+			fe->node = node;
+			fe->prop = prop;
+			fe->offset = m->offset;
+			fe->next = NULL;
+
+			/* search for an already existing fixup */
+			for_each_fixup(dt, f)
+				if (strcmp(f->ref, m->ref) == 0)
+					break;
+
+			/* no fixup found, add new */
+			if (f == NULL) {
+				f = xmalloc(sizeof(*f));
+				f->ref = m->ref;
+				f->entries = NULL;
+				f->next = NULL;
+
+				/* add it to the tree */
+				fp = &dt->fixups;
+				while (*fp)
+					fp = &(*fp)->next;
+				*fp = f;
+			}
+
+			/* and now append fixup entry */
+			fep = &f->entries;
+			while (*fep)
+				fep = &(*fep)->next;
+			*fep = fe;
+
+			/* mark the entry as unresolved */
+			phandle = 0xdeadbeef;
+		} else {
+			phandle = get_node_phandle(dt, refnode);
+
+			/* if it's a plugin, we need to record it */
+			if (symbol_fixup_support && dt->is_plugin) {
+
+				/* allocate a new local fixup entry */
+				fe = xmalloc(sizeof(*fe));
+
+				fe->node = node;
+				fe->prop = prop;
+				fe->offset = m->offset;
+				fe->next = NULL;
+
+				/* append it to the local fixups */
+				fep = &dt->local_fixups;
+				while (*fep)
+					fep = &(*fep)->next;
+				*fep = fe;
+			}
+		}
+
+		*((cell_t *)(prop->val.val + m->offset)) =
+			cpu_to_fdt32(phandle);
 	}
+
 }
 ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
       &duplicate_node_names, &explicit_phandles);
@@ -651,6 +722,45 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
 }
 TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
 
+static void check_auto_label_phandles(struct check *c, struct node *dt,
+				       struct node *node)
+{
+	struct label *l;
+	struct symbol *s, **sp;
+	int has_label;
+
+	if (!symbol_fixup_support)
+		return;
+
+	has_label = 0;
+	for_each_label(node->labels, l) {
+		has_label = 1;
+		break;
+	}
+
+	if (!has_label)
+		return;
+
+	/* force allocation of a phandle for this node */
+	(void)get_node_phandle(dt, node);
+
+	/* add the symbol */
+	for_each_label(node->labels, l) {
+
+		s = xmalloc(sizeof(*s));
+		s->label = l;
+		s->node = node;
+		s->next = NULL;
+
+		/* add it to the symbols list */
+		sp = &dt->symbols;
+		while (*sp)
+			sp = &((*sp)->next);
+		*sp = s;
+	}
+}
+NODE_WARNING(auto_label_phandles, NULL);
+
 static struct check *check_table[] = {
 	&duplicate_node_names, &duplicate_property_names,
 	&node_name_chars, &node_name_format, &property_name_chars,
@@ -669,6 +779,8 @@ static struct check *check_table[] = {
 	&avoid_default_addr_size,
 	&obsolete_chosen_interrupt_controller,
 
+	&auto_label_phandles,
+
 	&always_fail,
 };
 
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index 254d5af..2cef406 100644
--- a/scripts/dtc/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
@@ -112,6 +112,11 @@ static int pop_input_file(void);
 			return DT_V1;
 		}
 
+<*>"/plugin/"	{
+			DPRINT("Keyword: /plugin/\n");
+			return DT_PLUGIN;
+		}
+
 <*>"/memreserve/"	{
 			DPRINT("Keyword: /memreserve/\n");
 			BEGIN_DEFAULT();
diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
index a6c5fcd..90bfb9e 100644
--- a/scripts/dtc/dtc-lexer.lex.c_shipped
+++ b/scripts/dtc/dtc-lexer.lex.c_shipped
@@ -372,8 +372,8 @@ static void yy_fatal_error (yyconst char msg[]  );
 	*yy_cp = '\0'; \
 	(yy_c_buf_p) = yy_cp;
 
-#define YY_NUM_RULES 30
-#define YY_END_OF_BUFFER 31
+#define YY_NUM_RULES 31
+#define YY_END_OF_BUFFER 32
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -381,25 +381,26 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[161] =
+static yyconst flex_int16_t yy_accept[168] =
     {   0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       31,   29,   18,   18,   29,   29,   29,   29,   29,   29,
-       29,   29,   29,   29,   29,   29,   29,   29,   15,   16,
-       16,   29,   16,   10,   10,   18,   26,    0,    3,    0,
-       27,   12,    0,    0,   11,    0,    0,    0,    0,    0,
-        0,    0,   21,   23,   25,   24,   22,    0,    9,   28,
-        0,    0,    0,   14,   14,   16,   16,   16,   10,   10,
-       10,    0,   12,    0,   11,    0,    0,    0,   20,    0,
-        0,    0,    0,    0,    0,    0,    0,   16,   10,   10,
-       10,    0,   19,    0,    0,    0,    0,    0,    0,    0,
-
-        0,    0,   16,   13,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,   16,    6,    0,    0,    0,    0,    0,
-        0,    2,    0,    0,    0,    0,    0,    0,    0,    0,
-        4,   17,    0,    0,    2,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    1,    0,    0,
-        0,    0,    5,    8,    0,    0,    0,    0,    7,    0
+       32,   30,   19,   19,   30,   30,   30,   30,   30,   30,
+       30,   30,   30,   30,   30,   30,   30,   30,   16,   17,
+       17,   30,   17,   11,   11,   19,   27,    0,    3,    0,
+       28,   13,    0,    0,   12,    0,    0,    0,    0,    0,
+        0,    0,    0,   22,   24,   26,   25,   23,    0,   10,
+       29,    0,    0,    0,   15,   15,   17,   17,   17,   11,
+       11,   11,    0,   13,    0,   12,    0,    0,    0,   21,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   17,
+       11,   11,   11,    0,   20,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,   17,   14,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   17,    7,    0,
+        0,    0,    0,    0,    0,    0,    2,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    4,   18,    0,    0,
+        5,    2,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    1,    0,    0,    0,    0,    6,
+        9,    0,    0,    0,    0,    8,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -415,9 +416,9 @@ static yyconst flex_int32_t yy_ec[256] =
        21,   21,   21,   21,   23,   21,   21,   24,   21,   21,
         1,   25,   26,    1,   21,    1,   20,   27,   28,   29,
 
-       30,   20,   21,   21,   31,   21,   21,   32,   33,   34,
-       35,   36,   21,   37,   38,   39,   40,   41,   21,   24,
-       42,   21,   43,   44,   45,    1,    1,    1,    1,    1,
+       30,   20,   31,   21,   32,   21,   21,   33,   34,   35,
+       36,   37,   21,   38,   39,   40,   41,   42,   21,   24,
+       43,   21,   44,   45,   46,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -434,163 +435,167 @@ static yyconst flex_int32_t yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int32_t yy_meta[46] =
+static yyconst flex_int32_t yy_meta[47] =
     {   0,
         1,    1,    1,    1,    1,    2,    3,    1,    2,    2,
         2,    4,    5,    5,    5,    6,    1,    1,    1,    7,
         8,    8,    8,    8,    1,    1,    7,    7,    7,    7,
         8,    8,    8,    8,    8,    8,    8,    8,    8,    8,
-        8,    8,    3,    1,    1
+        8,    8,    8,    3,    1,    1
     } ;
 
-static yyconst flex_int16_t yy_base[175] =
+static yyconst flex_int16_t yy_base[182] =
     {   0,
-        0,  388,  381,   40,   41,  386,   71,  385,   34,   44,
-      390,  395,   60,   62,  371,  112,  111,  111,  111,  104,
-      370,  106,  371,  342,  124,  119,    0,  144,  395,    0,
-      123,    0,  159,  153,  165,  167,  395,  130,  395,  382,
-      395,    0,  372,  122,  395,  157,  374,  379,  350,   21,
-      346,  349,  395,  395,  395,  395,  395,  362,  395,  395,
-      181,  346,  342,  395,  359,    0,  191,  343,  190,  351,
-      350,    0,    0,    0,  173,  362,  177,  367,  357,  329,
-      335,  328,  337,  331,  206,  329,  334,  327,  395,  338,
-      170,  314,  346,  345,  318,  325,  343,  158,  316,  212,
-
-      322,  319,  320,  395,  340,  336,  308,  305,  314,  304,
-      295,  138,  208,  220,  395,  292,  305,  265,  264,  254,
-      201,  222,  285,  275,  273,  270,  236,  235,  225,  115,
-      395,  395,  252,  216,  216,  217,  214,  230,  209,  220,
-      213,  239,  211,  217,  216,  209,  229,  395,  240,  225,
-      206,  169,  395,  395,  116,  106,   99,   54,  395,  395,
-      254,  260,  268,  272,  276,  282,  289,  293,  301,  309,
-      313,  319,  327,  335
+        0,  392,  385,   41,   42,  390,   72,  389,   35,   45,
+      394,  399,   61,   63,  375,  114,  113,  113,  149,  105,
+      374,  106,  375,  345,  126,  357,    0,  174,  399,    0,
+      121,    0,  131,  127,  130,  133,  399,  121,  399,  385,
+      399,    0,  375,  140,  399,  146,  377,  382,  352,  126,
+      348,  352,  348,  399,  399,  399,  399,  399,  364,  399,
+      399,  160,  347,  343,  399,  361,    0,  189,  344,  193,
+      353,  352,    0,    0,    0,  147,  364,  158,  369,  359,
+      330,  336,  329,  339,  332,  324,  207,  329,  335,  327,
+      399,  339,  146,  314,  347,  346,  318,  326,  344,   34,
+
+      316,  322,  177,  322,  318,  320,  399,  340,  336,  307,
+      304,  313,  303,  313,  310,  172,  182,  189,  399,  311,
+      326,  304,  309,  298,  301,  188,  209,  314,  303,  299,
+      279,  255,  254,  268,  215,  188,  399,  399,  266,  239,
+      399,  218,  238,  220,  232,  215,  227,  209,  236,  219,
+      213,  212,  203,  221,  399,  233,  215,  207,  184,  399,
+      399,  158,  120,  104,   40,  399,  399,  246,  252,  260,
+      264,  268,  274,  281,  285,  293,  301,  305,  311,  319,
+      327
     } ;
 
-static yyconst flex_int16_t yy_def[175] =
+static yyconst flex_int16_t yy_def[182] =
     {   0,
-      160,    1,    1,    1,    1,    5,  160,    7,    1,    1,
-      160,  160,  160,  160,  160,  161,  162,  163,  160,  160,
-      160,  160,  164,  160,  160,  160,  165,  164,  160,  166,
-      167,  166,  166,  160,  160,  160,  160,  161,  160,  161,
-      160,  168,  160,  163,  160,  163,  169,  170,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  164,  160,  160,
-      160,  160,  160,  160,  164,  166,  167,  166,  160,  160,
-      160,  171,  168,  172,  163,  169,  169,  170,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  166,  160,  160,
-      171,  172,  160,  160,  160,  160,  160,  160,  160,  160,
-
-      160,  160,  166,  160,  160,  160,  160,  160,  160,  160,
-      160,  173,  160,  166,  160,  160,  160,  160,  160,  160,
-      173,  160,  173,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  174,  160,  160,  160,  174,  160,  174,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,    0,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160
+      167,    1,    1,    1,    1,    5,  167,    7,    1,    1,
+      167,  167,  167,  167,  167,  168,  169,  170,  167,  167,
+      167,  167,  171,  167,  167,   19,  172,  171,  167,  173,
+      174,  173,  173,  167,  167,  167,  167,  168,  167,  168,
+      167,  175,  167,  170,  167,  170,  176,  177,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  171,  167,
+      167,  167,  167,  167,  167,  171,  173,  174,  173,  167,
+      167,  167,  178,  175,  179,  170,  176,  176,  177,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  173,
+      167,  167,  178,  179,  167,  167,  167,  167,  167,  167,
+
+      167,  167,  167,  167,  167,  173,  167,  167,  167,  167,
+      167,  167,  167,  167,  167,  180,  167,  173,  167,  167,
+      167,  167,  167,  167,  167,  180,  167,  180,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  181,
+      167,  167,  167,  181,  167,  181,  167,  167,  167,  167,
+      167,  167,  167,  167,  167,  167,    0,  167,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167
     } ;
 
-static yyconst flex_int16_t yy_nxt[441] =
+static yyconst flex_int16_t yy_nxt[446] =
     {   0,
        12,   13,   14,   15,   16,   12,   17,   18,   12,   12,
        12,   19,   12,   12,   12,   12,   20,   21,   22,   23,
        23,   23,   23,   23,   12,   12,   23,   23,   23,   23,
        23,   23,   23,   23,   23,   23,   23,   23,   23,   23,
-       23,   23,   12,   24,   12,   25,   34,   35,   35,   25,
-       81,   26,   26,   27,   27,   27,   34,   35,   35,   82,
-       28,   36,   36,   36,   36,  159,   29,   28,   28,   28,
-       28,   12,   13,   14,   15,   16,   30,   17,   18,   30,
-       30,   30,   26,   30,   30,   30,   12,   20,   21,   22,
-       31,   31,   31,   31,   31,   32,   12,   31,   31,   31,
+       23,   23,   23,   12,   24,   12,   25,   34,   35,   35,
+       25,  166,   26,   26,   27,   27,   27,   34,   35,   35,
+      112,   28,   36,   36,   36,   36,  113,   29,   28,   28,
+       28,   28,   12,   13,   14,   15,   16,   30,   17,   18,
+       30,   30,   30,   26,   30,   30,   30,   12,   20,   21,
+       22,   31,   31,   31,   31,   31,   32,   12,   31,   31,
 
        31,   31,   31,   31,   31,   31,   31,   31,   31,   31,
-       31,   31,   31,   12,   24,   12,   39,   41,   45,   47,
-       53,   54,   48,   56,   57,   61,   61,   47,   66,   45,
-       48,   66,   66,   66,   39,   46,   40,   49,   59,   50,
-      158,   51,  122,   52,  157,   49,   46,   50,  136,   63,
-      137,   52,  156,   43,   40,   62,   65,   65,   65,   59,
-       61,   61,  123,   65,   75,   69,   69,   69,   36,   36,
-       65,   65,   65,   65,   70,   71,   72,   69,   69,   69,
-       45,   46,   61,   61,  109,   77,   70,   71,   93,  110,
-       68,   70,   71,   85,   85,   85,   66,   46,  155,   66,
-
-       66,   66,   69,   69,   69,  122,   59,  100,  100,   61,
-       61,   70,   71,  100,  100,  148,  112,  154,   85,   85,
-       85,   61,   61,  129,  129,  123,  129,  129,  135,  135,
-      135,  142,  142,  148,  143,  149,  153,  135,  135,  135,
-      142,  142,  160,  143,  152,  151,  150,  146,  145,  144,
-      141,  140,  139,  149,   38,   38,   38,   38,   38,   38,
-       38,   38,   42,  138,  134,  133,   42,   42,   44,   44,
-       44,   44,   44,   44,   44,   44,   58,   58,   58,   58,
-       64,  132,   64,   66,  131,  130,   66,  160,   66,   66,
-       67,  128,  127,   67,   67,   67,   67,   73,  126,   73,
-
-       73,   76,   76,   76,   76,   76,   76,   76,   76,   78,
-       78,   78,   78,   78,   78,   78,   78,   91,  125,   91,
-       92,  124,   92,   92,  120,   92,   92,  121,  121,  121,
-      121,  121,  121,  121,  121,  147,  147,  147,  147,  147,
-      147,  147,  147,  119,  118,  117,  116,  115,   47,  114,
-      110,  113,  111,  108,  107,  106,   48,  105,  104,   89,
-      103,  102,  101,   99,   98,   97,   96,   95,   94,   79,
-       77,   90,   89,   88,   59,   87,   86,   59,   84,   83,
-       80,   79,   77,   74,  160,   60,   59,   55,   37,  160,
-       33,   25,   26,   25,   11,  160,  160,  160,  160,  160,
-
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160
+       31,   31,   31,   31,   31,   12,   24,   12,   39,   41,
+       45,   54,   55,   57,   58,   39,   67,   62,   62,   67,
+       67,   67,   62,   62,   36,   36,   60,   46,   40,   70,
+       70,   70,   70,   70,   70,   40,  165,   45,   71,   72,
+       73,   71,   72,   76,   45,   82,   43,   47,   63,  164,
+       48,   62,   62,   69,   46,   83,   78,   71,   72,   95,
+       46,   46,   87,   87,   87,   49,  127,   50,  103,  103,
+       51,  116,   52,   62,   62,   53,   66,   66,   66,   60,
+       62,   62,  127,   66,   67,  163,  128,   67,   67,   67,
+
+       66,   66,   66,   66,   60,   70,   70,   70,  103,  103,
+      135,  135,  128,  162,   71,   72,  135,  135,  161,   87,
+       87,   87,  143,  155,  144,  155,  160,  142,  142,  142,
+      142,  142,  142,  149,  149,  167,  150,  149,  149,  159,
+      150,  158,  157,  156,  153,  156,   38,   38,   38,   38,
+       38,   38,   38,   38,   42,  152,  151,  148,   42,   42,
+       44,   44,   44,   44,   44,   44,   44,   44,   59,   59,
+       59,   59,   65,  147,   65,   67,  146,  145,   67,  141,
+       67,   67,   68,  140,  139,   68,   68,   68,   68,   74,
+      138,   74,   74,   77,   77,   77,   77,   77,   77,   77,
+
+       77,   79,   79,   79,   79,   79,   79,   79,   79,   93,
+      137,   93,   94,  136,   94,   94,  167,   94,   94,  126,
+      126,  126,  126,  126,  126,  126,  126,  154,  154,  154,
+      154,  154,  154,  154,  154,  134,  133,  132,  131,  130,
+      129,  125,  124,  123,  122,  121,  120,  119,   47,  118,
+      113,  117,  115,  114,  111,  110,  109,   48,  108,  107,
+       91,  106,  105,  104,  102,  101,  100,   99,   98,   97,
+       96,   80,   78,   92,   91,   90,   60,   89,   88,   60,
+       86,   85,   84,   81,   80,   78,   75,  167,   64,   61,
+       60,   56,   37,  167,   33,   25,   26,   25,   11,  167,
+
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167,  167,  167,  167,  167
     } ;
 
-static yyconst flex_int16_t yy_chk[441] =
+static yyconst flex_int16_t yy_chk[446] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    4,    9,    9,    9,   10,
-       50,    4,    5,    5,    5,    5,   10,   10,   10,   50,
-        5,   13,   13,   14,   14,  158,    5,    5,    5,    5,
-        5,    7,    7,    7,    7,    7,    7,    7,    7,    7,
+        1,    1,    1,    1,    1,    1,    4,    9,    9,    9,
+       10,  165,    4,    5,    5,    5,    5,   10,   10,   10,
+      100,    5,   13,   13,   14,   14,  100,    5,    5,    5,
+        5,    5,    7,    7,    7,    7,    7,    7,    7,    7,
         7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
         7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
 
         7,    7,    7,    7,    7,    7,    7,    7,    7,    7,
-        7,    7,    7,    7,    7,    7,   16,   17,   18,   19,
-       20,   20,   19,   22,   22,   25,   25,   26,   31,   44,
-       26,   31,   31,   31,   38,   18,   16,   19,   31,   19,
-      157,   19,  112,   19,  156,   26,   44,   26,  130,   26,
-      130,   26,  155,   17,   38,   25,   28,   28,   28,   28,
-       33,   33,  112,   28,   46,   34,   34,   34,   36,   36,
-       28,   28,   28,   28,   34,   34,   34,   35,   35,   35,
-       75,   46,   61,   61,   98,   77,   35,   35,   77,   98,
-       33,   91,   91,   61,   61,   61,   67,   75,  152,   67,
-
-       67,   67,   69,   69,   69,  121,   67,   85,   85,  113,
-      113,   69,   69,  100,  100,  143,  100,  151,   85,   85,
-       85,  114,  114,  122,  122,  121,  129,  129,  135,  135,
-      135,  138,  138,  147,  138,  143,  150,  129,  129,  129,
-      142,  142,  149,  142,  146,  145,  144,  141,  140,  139,
-      137,  136,  134,  147,  161,  161,  161,  161,  161,  161,
-      161,  161,  162,  133,  128,  127,  162,  162,  163,  163,
-      163,  163,  163,  163,  163,  163,  164,  164,  164,  164,
-      165,  126,  165,  166,  125,  124,  166,  123,  166,  166,
-      167,  120,  119,  167,  167,  167,  167,  168,  118,  168,
-
-      168,  169,  169,  169,  169,  169,  169,  169,  169,  170,
-      170,  170,  170,  170,  170,  170,  170,  171,  117,  171,
-      172,  116,  172,  172,  111,  172,  172,  173,  173,  173,
-      173,  173,  173,  173,  173,  174,  174,  174,  174,  174,
-      174,  174,  174,  110,  109,  108,  107,  106,  105,  103,
-      102,  101,   99,   97,   96,   95,   94,   93,   92,   90,
-       88,   87,   86,   84,   83,   82,   81,   80,   79,   78,
-       76,   71,   70,   68,   65,   63,   62,   58,   52,   51,
-       49,   48,   47,   43,   40,   24,   23,   21,   15,   11,
-        8,    6,    3,    2,  160,  160,  160,  160,  160,  160,
-
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160,
-      160,  160,  160,  160,  160,  160,  160,  160,  160,  160
+        7,    7,    7,    7,    7,    7,    7,    7,   16,   17,
+       18,   20,   20,   22,   22,   38,   31,   25,   25,   31,
+       31,   31,   33,   33,   36,   36,   31,   18,   16,   34,
+       34,   34,   35,   35,   35,   38,  164,   44,   34,   34,
+       34,   35,   35,   46,   76,   50,   17,   19,   25,  163,
+       19,   62,   62,   33,   44,   50,   78,   93,   93,   78,
+       46,   76,   62,   62,   62,   19,  116,   19,  103,  103,
+       19,  103,   19,  117,  117,   19,   28,   28,   28,   28,
+      118,  118,  126,   28,   68,  162,  116,   68,   68,   68,
+
+       28,   28,   28,   28,   68,   70,   70,   70,   87,   87,
+      127,  127,  126,  159,   70,   70,  135,  135,  158,   87,
+       87,   87,  136,  150,  136,  154,  157,  135,  135,  135,
+      142,  142,  142,  145,  145,  156,  145,  149,  149,  153,
+      149,  152,  151,  150,  148,  154,  168,  168,  168,  168,
+      168,  168,  168,  168,  169,  147,  146,  144,  169,  169,
+      170,  170,  170,  170,  170,  170,  170,  170,  171,  171,
+      171,  171,  172,  143,  172,  173,  140,  139,  173,  134,
+      173,  173,  174,  133,  132,  174,  174,  174,  174,  175,
+      131,  175,  175,  176,  176,  176,  176,  176,  176,  176,
+
+      176,  177,  177,  177,  177,  177,  177,  177,  177,  178,
+      130,  178,  179,  129,  179,  179,  128,  179,  179,  180,
+      180,  180,  180,  180,  180,  180,  180,  181,  181,  181,
+      181,  181,  181,  181,  181,  125,  124,  123,  122,  121,
+      120,  115,  114,  113,  112,  111,  110,  109,  108,  106,
+      105,  104,  102,  101,   99,   98,   97,   96,   95,   94,
+       92,   90,   89,   88,   86,   85,   84,   83,   82,   81,
+       80,   79,   77,   72,   71,   69,   66,   64,   63,   59,
+       53,   52,   51,   49,   48,   47,   43,   40,   26,   24,
+       23,   21,   15,   11,    8,    6,    3,    2,  167,  167,
+
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167,  167,  167,  167,  167
     } ;
 
 static yy_state_type yy_last_accepting_state;
@@ -660,7 +665,7 @@ static int dts_version = 1;
 
 static void push_input_file(const char *filename);
 static int pop_input_file(void);
-#line 664 "dtc-lexer.lex.c"
+#line 669 "dtc-lexer.lex.c"
 
 #define INITIAL 0
 #define INCLUDE 1
@@ -854,7 +859,7 @@ YY_DECL
     
 #line 67 "dtc-lexer.l"
 
-#line 858 "dtc-lexer.lex.c"
+#line 863 "dtc-lexer.lex.c"
 
 	if ( !(yy_init) )
 		{
@@ -908,13 +913,13 @@ yy_match:
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 161 )
+				if ( yy_current_state >= 168 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			++yy_cp;
 			}
-		while ( yy_current_state != 160 );
+		while ( yy_current_state != 167 );
 		yy_cp = (yy_last_accepting_cpos);
 		yy_current_state = (yy_last_accepting_state);
 
@@ -1006,23 +1011,31 @@ case 5:
 YY_RULE_SETUP
 #line 115 "dtc-lexer.l"
 {
+			DPRINT("Keyword: /plugin/\n");
+			return DT_PLUGIN;
+		}
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 120 "dtc-lexer.l"
+{
 			DPRINT("Keyword: /memreserve/\n");
 			BEGIN_DEFAULT();
 			return DT_MEMRESERVE;
 		}
 	YY_BREAK
-case 6:
+case 7:
 YY_RULE_SETUP
-#line 121 "dtc-lexer.l"
+#line 126 "dtc-lexer.l"
 {
 			DPRINT("Keyword: /bits/\n");
 			BEGIN_DEFAULT();
 			return DT_BITS;
 		}
 	YY_BREAK
-case 7:
+case 8:
 YY_RULE_SETUP
-#line 127 "dtc-lexer.l"
+#line 132 "dtc-lexer.l"
 {
 			DPRINT("Keyword: /delete-property/\n");
 			DPRINT("<PROPNODENAME>\n");
@@ -1030,9 +1043,9 @@ YY_RULE_SETUP
 			return DT_DEL_PROP;
 		}
 	YY_BREAK
-case 8:
+case 9:
 YY_RULE_SETUP
-#line 134 "dtc-lexer.l"
+#line 139 "dtc-lexer.l"
 {
 			DPRINT("Keyword: /delete-node/\n");
 			DPRINT("<PROPNODENAME>\n");
@@ -1040,9 +1053,9 @@ YY_RULE_SETUP
 			return DT_DEL_NODE;
 		}
 	YY_BREAK
-case 9:
+case 10:
 YY_RULE_SETUP
-#line 141 "dtc-lexer.l"
+#line 146 "dtc-lexer.l"
 {
 			DPRINT("Label: %s\n", yytext);
 			yylval.labelref = xstrdup(yytext);
@@ -1050,19 +1063,19 @@ YY_RULE_SETUP
 			return DT_LABEL;
 		}
 	YY_BREAK
-case 10:
+case 11:
 YY_RULE_SETUP
-#line 148 "dtc-lexer.l"
+#line 153 "dtc-lexer.l"
 {
 			yylval.literal = xstrdup(yytext);
 			DPRINT("Literal: '%s'\n", yylval.literal);
 			return DT_LITERAL;
 		}
 	YY_BREAK
-case 11:
-/* rule 11 can match eol */
+case 12:
+/* rule 12 can match eol */
 YY_RULE_SETUP
-#line 154 "dtc-lexer.l"
+#line 159 "dtc-lexer.l"
 {
 			yytext[yyleng-1] = '\0';
 			yylval.literal = xstrdup(yytext+1);
@@ -1070,18 +1083,18 @@ YY_RULE_SETUP
 			return DT_CHAR_LITERAL;
 		}
 	YY_BREAK
-case 12:
+case 13:
 YY_RULE_SETUP
-#line 161 "dtc-lexer.l"
+#line 166 "dtc-lexer.l"
 {	/* label reference */
 			DPRINT("Ref: %s\n", yytext+1);
 			yylval.labelref = xstrdup(yytext+1);
 			return DT_REF;
 		}
 	YY_BREAK
-case 13:
+case 14:
 YY_RULE_SETUP
-#line 167 "dtc-lexer.l"
+#line 172 "dtc-lexer.l"
 {	/* new-style path reference */
 			yytext[yyleng-1] = '\0';
 			DPRINT("Ref: %s\n", yytext+2);
@@ -1089,27 +1102,27 @@ YY_RULE_SETUP
 			return DT_REF;
 		}
 	YY_BREAK
-case 14:
+case 15:
 YY_RULE_SETUP
-#line 174 "dtc-lexer.l"
+#line 179 "dtc-lexer.l"
 {
 			yylval.byte = strtol(yytext, NULL, 16);
 			DPRINT("Byte: %02x\n", (int)yylval.byte);
 			return DT_BYTE;
 		}
 	YY_BREAK
-case 15:
+case 16:
 YY_RULE_SETUP
-#line 180 "dtc-lexer.l"
+#line 185 "dtc-lexer.l"
 {
 			DPRINT("/BYTESTRING\n");
 			BEGIN_DEFAULT();
 			return ']';
 		}
 	YY_BREAK
-case 16:
+case 17:
 YY_RULE_SETUP
-#line 186 "dtc-lexer.l"
+#line 191 "dtc-lexer.l"
 {
 			DPRINT("PropNodeName: %s\n", yytext);
 			yylval.propnodename = xstrdup((yytext[0] == '\\') ?
@@ -1118,75 +1131,75 @@ YY_RULE_SETUP
 			return DT_PROPNODENAME;
 		}
 	YY_BREAK
-case 17:
+case 18:
 YY_RULE_SETUP
-#line 194 "dtc-lexer.l"
+#line 199 "dtc-lexer.l"
 {
 			DPRINT("Binary Include\n");
 			return DT_INCBIN;
 		}
 	YY_BREAK
-case 18:
-/* rule 18 can match eol */
-YY_RULE_SETUP
-#line 199 "dtc-lexer.l"
-/* eat whitespace */
-	YY_BREAK
 case 19:
 /* rule 19 can match eol */
 YY_RULE_SETUP
-#line 200 "dtc-lexer.l"
-/* eat C-style comments */
+#line 204 "dtc-lexer.l"
+/* eat whitespace */
 	YY_BREAK
 case 20:
 /* rule 20 can match eol */
 YY_RULE_SETUP
-#line 201 "dtc-lexer.l"
-/* eat C++-style comments */
+#line 205 "dtc-lexer.l"
+/* eat C-style comments */
 	YY_BREAK
 case 21:
+/* rule 21 can match eol */
 YY_RULE_SETUP
-#line 203 "dtc-lexer.l"
-{ return DT_LSHIFT; };
+#line 206 "dtc-lexer.l"
+/* eat C++-style comments */
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 204 "dtc-lexer.l"
-{ return DT_RSHIFT; };
+#line 208 "dtc-lexer.l"
+{ return DT_LSHIFT; };
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 205 "dtc-lexer.l"
-{ return DT_LE; };
+#line 209 "dtc-lexer.l"
+{ return DT_RSHIFT; };
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 206 "dtc-lexer.l"
-{ return DT_GE; };
+#line 210 "dtc-lexer.l"
+{ return DT_LE; };
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 207 "dtc-lexer.l"
-{ return DT_EQ; };
+#line 211 "dtc-lexer.l"
+{ return DT_GE; };
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 208 "dtc-lexer.l"
-{ return DT_NE; };
+#line 212 "dtc-lexer.l"
+{ return DT_EQ; };
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 209 "dtc-lexer.l"
-{ return DT_AND; };
+#line 213 "dtc-lexer.l"
+{ return DT_NE; };
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 210 "dtc-lexer.l"
-{ return DT_OR; };
+#line 214 "dtc-lexer.l"
+{ return DT_AND; };
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 212 "dtc-lexer.l"
+#line 215 "dtc-lexer.l"
+{ return DT_OR; };
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 217 "dtc-lexer.l"
 {
 			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
 				(unsigned)yytext[0]);
@@ -1202,12 +1215,12 @@ YY_RULE_SETUP
 			return yytext[0];
 		}
 	YY_BREAK
-case 30:
+case 31:
 YY_RULE_SETUP
-#line 227 "dtc-lexer.l"
+#line 232 "dtc-lexer.l"
 ECHO;
 	YY_BREAK
-#line 1211 "dtc-lexer.lex.c"
+#line 1224 "dtc-lexer.lex.c"
 
 	case YY_END_OF_BUFFER:
 		{
@@ -1499,7 +1512,7 @@ static int yy_get_next_buffer (void)
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 161 )
+			if ( yy_current_state >= 168 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1527,11 +1540,11 @@ static int yy_get_next_buffer (void)
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 161 )
+		if ( yy_current_state >= 168 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 160);
+	yy_is_jam = (yy_current_state == 167);
 
 	return yy_is_jam ? 0 : yy_current_state;
 }
@@ -2166,7 +2179,7 @@ void yyfree (void * ptr )
 
 #define YYTABLES_NAME "yytables"
 
-#line 227 "dtc-lexer.l"
+#line 232 "dtc-lexer.l"
 
 
 
diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
index 4af5590..2977268 100644
--- a/scripts/dtc/dtc-parser.tab.c_shipped
+++ b/scripts/dtc/dtc-parser.tab.c_shipped
@@ -71,6 +71,7 @@
 #line 21 "dtc-parser.y"
 
 #include <stdio.h>
+#include <inttypes.h>
 
 #include "dtc.h"
 #include "srcpos.h"
@@ -89,7 +90,7 @@ static unsigned char eval_char_literal(const char *s);
 
 
 /* Line 189 of yacc.c  */
-#line 93 "dtc-parser.tab.c"
+#line 94 "dtc-parser.tab.c"
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
@@ -117,27 +118,28 @@ static unsigned char eval_char_literal(const char *s);
       know about them.  */
    enum yytokentype {
      DT_V1 = 258,
-     DT_MEMRESERVE = 259,
-     DT_LSHIFT = 260,
-     DT_RSHIFT = 261,
-     DT_LE = 262,
-     DT_GE = 263,
-     DT_EQ = 264,
-     DT_NE = 265,
-     DT_AND = 266,
-     DT_OR = 267,
-     DT_BITS = 268,
-     DT_DEL_PROP = 269,
-     DT_DEL_NODE = 270,
-     DT_PROPNODENAME = 271,
-     DT_LITERAL = 272,
-     DT_CHAR_LITERAL = 273,
-     DT_BASE = 274,
-     DT_BYTE = 275,
-     DT_STRING = 276,
-     DT_LABEL = 277,
-     DT_REF = 278,
-     DT_INCBIN = 279
+     DT_PLUGIN = 259,
+     DT_MEMRESERVE = 260,
+     DT_LSHIFT = 261,
+     DT_RSHIFT = 262,
+     DT_LE = 263,
+     DT_GE = 264,
+     DT_EQ = 265,
+     DT_NE = 266,
+     DT_AND = 267,
+     DT_OR = 268,
+     DT_BITS = 269,
+     DT_DEL_PROP = 270,
+     DT_DEL_NODE = 271,
+     DT_PROPNODENAME = 272,
+     DT_LITERAL = 273,
+     DT_CHAR_LITERAL = 274,
+     DT_BASE = 275,
+     DT_BYTE = 276,
+     DT_STRING = 277,
+     DT_LABEL = 278,
+     DT_REF = 279,
+     DT_INCBIN = 280
    };
 #endif
 
@@ -148,7 +150,7 @@ typedef union YYSTYPE
 {
 
 /* Line 214 of yacc.c  */
-#line 40 "dtc-parser.y"
+#line 41 "dtc-parser.y"
 
 	char *propnodename;
 	char *literal;
@@ -168,11 +170,12 @@ typedef union YYSTYPE
 	struct node *nodelist;
 	struct reserve_info *re;
 	uint64_t integer;
+	int is_plugin;
 
 
 
 /* Line 214 of yacc.c  */
-#line 176 "dtc-parser.tab.c"
+#line 179 "dtc-parser.tab.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -184,7 +187,7 @@ typedef union YYSTYPE
 
 
 /* Line 264 of yacc.c  */
-#line 188 "dtc-parser.tab.c"
+#line 191 "dtc-parser.tab.c"
 
 #ifdef short
 # undef short
@@ -399,20 +402,20 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  4
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   133
+#define YYLAST   134
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  48
+#define YYNTOKENS  49
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  28
+#define YYNNTS  29
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  79
+#define YYNRULES  81
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  141
+#define YYNSTATES  144
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   279
+#define YYMAXUTOK   280
 
 #define YYTRANSLATE(YYX)						\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -423,16 +426,16 @@ static const yytype_uint8 yytranslate[] =
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    47,     2,     2,     2,    45,    41,     2,
-      33,    35,    44,    42,    34,    43,     2,    26,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,    38,    25,
-      36,    29,    30,    37,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    48,     2,     2,     2,    46,    42,     2,
+      34,    36,    45,    43,    35,    44,     2,    27,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    39,    26,
+      37,    30,    31,    38,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    31,     2,    32,    40,     2,     2,     2,     2,     2,
+       2,    32,     2,    33,    41,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    27,    39,    28,    46,     2,     2,     2,
+       2,     2,     2,    28,    40,    29,    47,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -447,7 +450,8 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25
 };
 
 #if YYDEBUG
@@ -455,59 +459,61 @@ static const yytype_uint8 yytranslate[] =
    YYRHS.  */
 static const yytype_uint16 yyprhs[] =
 {
-       0,     0,     3,     8,     9,    12,    17,    20,    23,    27,
-      31,    36,    42,    43,    46,    51,    54,    58,    61,    64,
-      68,    73,    76,    86,    92,    95,    96,    99,   102,   106,
-     108,   111,   114,   117,   119,   121,   125,   127,   129,   135,
-     137,   141,   143,   147,   149,   153,   155,   159,   161,   165,
-     167,   171,   175,   177,   181,   185,   189,   193,   197,   201,
-     203,   207,   211,   213,   217,   221,   225,   227,   229,   232,
-     235,   238,   239,   242,   245,   246,   249,   252,   255,   259
+       0,     0,     3,     9,    10,    13,    14,    17,    22,    25,
+      28,    32,    36,    41,    47,    48,    51,    56,    59,    63,
+      66,    69,    73,    78,    81,    91,    97,   100,   101,   104,
+     107,   111,   113,   116,   119,   122,   124,   126,   130,   132,
+     134,   140,   142,   146,   148,   152,   154,   158,   160,   164,
+     166,   170,   172,   176,   180,   182,   186,   190,   194,   198,
+     202,   206,   208,   212,   216,   218,   222,   226,   230,   232,
+     234,   237,   240,   243,   244,   247,   250,   251,   254,   257,
+     260,   264
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      49,     0,    -1,     3,    25,    50,    52,    -1,    -1,    51,
-      50,    -1,     4,    59,    59,    25,    -1,    22,    51,    -1,
-      26,    53,    -1,    52,    26,    53,    -1,    52,    23,    53,
-      -1,    52,    15,    23,    25,    -1,    27,    54,    74,    28,
-      25,    -1,    -1,    54,    55,    -1,    16,    29,    56,    25,
-      -1,    16,    25,    -1,    14,    16,    25,    -1,    22,    55,
-      -1,    57,    21,    -1,    57,    58,    30,    -1,    57,    31,
-      73,    32,    -1,    57,    23,    -1,    57,    24,    33,    21,
-      34,    59,    34,    59,    35,    -1,    57,    24,    33,    21,
-      35,    -1,    56,    22,    -1,    -1,    56,    34,    -1,    57,
-      22,    -1,    13,    17,    36,    -1,    36,    -1,    58,    59,
-      -1,    58,    23,    -1,    58,    22,    -1,    17,    -1,    18,
-      -1,    33,    60,    35,    -1,    61,    -1,    62,    -1,    62,
-      37,    60,    38,    61,    -1,    63,    -1,    62,    12,    63,
-      -1,    64,    -1,    63,    11,    64,    -1,    65,    -1,    64,
-      39,    65,    -1,    66,    -1,    65,    40,    66,    -1,    67,
-      -1,    66,    41,    67,    -1,    68,    -1,    67,     9,    68,
-      -1,    67,    10,    68,    -1,    69,    -1,    68,    36,    69,
-      -1,    68,    30,    69,    -1,    68,     7,    69,    -1,    68,
-       8,    69,    -1,    69,     5,    70,    -1,    69,     6,    70,
-      -1,    70,    -1,    70,    42,    71,    -1,    70,    43,    71,
-      -1,    71,    -1,    71,    44,    72,    -1,    71,    26,    72,
-      -1,    71,    45,    72,    -1,    72,    -1,    59,    -1,    43,
-      72,    -1,    46,    72,    -1,    47,    72,    -1,    -1,    73,
-      20,    -1,    73,    22,    -1,    -1,    75,    74,    -1,    75,
-      55,    -1,    16,    53,    -1,    15,    16,    25,    -1,    22,
-      75,    -1
+      50,     0,    -1,     3,    26,    51,    52,    54,    -1,    -1,
+       4,    26,    -1,    -1,    53,    52,    -1,     5,    61,    61,
+      26,    -1,    23,    53,    -1,    27,    55,    -1,    54,    27,
+      55,    -1,    54,    24,    55,    -1,    54,    16,    24,    26,
+      -1,    28,    56,    76,    29,    26,    -1,    -1,    56,    57,
+      -1,    17,    30,    58,    26,    -1,    17,    26,    -1,    15,
+      17,    26,    -1,    23,    57,    -1,    59,    22,    -1,    59,
+      60,    31,    -1,    59,    32,    75,    33,    -1,    59,    24,
+      -1,    59,    25,    34,    22,    35,    61,    35,    61,    36,
+      -1,    59,    25,    34,    22,    36,    -1,    58,    23,    -1,
+      -1,    58,    35,    -1,    59,    23,    -1,    14,    18,    37,
+      -1,    37,    -1,    60,    61,    -1,    60,    24,    -1,    60,
+      23,    -1,    18,    -1,    19,    -1,    34,    62,    36,    -1,
+      63,    -1,    64,    -1,    64,    38,    62,    39,    63,    -1,
+      65,    -1,    64,    13,    65,    -1,    66,    -1,    65,    12,
+      66,    -1,    67,    -1,    66,    40,    67,    -1,    68,    -1,
+      67,    41,    68,    -1,    69,    -1,    68,    42,    69,    -1,
+      70,    -1,    69,    10,    70,    -1,    69,    11,    70,    -1,
+      71,    -1,    70,    37,    71,    -1,    70,    31,    71,    -1,
+      70,     8,    71,    -1,    70,     9,    71,    -1,    71,     6,
+      72,    -1,    71,     7,    72,    -1,    72,    -1,    72,    43,
+      73,    -1,    72,    44,    73,    -1,    73,    -1,    73,    45,
+      74,    -1,    73,    27,    74,    -1,    73,    46,    74,    -1,
+      74,    -1,    61,    -1,    44,    74,    -1,    47,    74,    -1,
+      48,    74,    -1,    -1,    75,    21,    -1,    75,    23,    -1,
+      -1,    77,    76,    -1,    77,    57,    -1,    17,    55,    -1,
+      16,    17,    26,    -1,    23,    77,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   109,   109,   118,   121,   128,   132,   140,   144,   148,
-     158,   172,   180,   183,   190,   194,   198,   202,   210,   214,
-     218,   222,   226,   243,   253,   261,   264,   268,   275,   290,
-     295,   315,   329,   336,   340,   344,   351,   355,   356,   360,
-     361,   365,   366,   370,   371,   375,   376,   380,   381,   385,
-     386,   387,   391,   392,   393,   394,   395,   399,   400,   401,
-     405,   406,   407,   411,   412,   413,   414,   418,   419,   420,
-     421,   426,   429,   433,   441,   444,   448,   456,   460,   464
+       0,   113,   113,   124,   127,   135,   138,   145,   149,   157,
+     161,   165,   175,   189,   197,   200,   207,   211,   215,   219,
+     227,   231,   235,   239,   243,   260,   270,   278,   281,   285,
+     292,   307,   312,   332,   346,   353,   357,   361,   368,   372,
+     373,   377,   378,   382,   383,   387,   388,   392,   393,   397,
+     398,   402,   403,   404,   408,   409,   410,   411,   412,   416,
+     417,   418,   422,   423,   424,   428,   429,   430,   431,   435,
+     436,   437,   438,   443,   446,   450,   458,   461,   465,   473,
+     477,   481
 };
 #endif
 
@@ -516,19 +522,20 @@ static const yytype_uint16 yyrline[] =
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
-  "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", "DT_LSHIFT",
-  "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", "DT_OR",
-  "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", "DT_LITERAL",
-  "DT_CHAR_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING", "DT_LABEL",
-  "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['",
-  "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'",
-  "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
-  "memreserves", "memreserve", "devicetree", "nodedef", "proplist",
-  "propdef", "propdata", "propdataprefix", "arrayprefix", "integer_prim",
-  "integer_expr", "integer_trinary", "integer_or", "integer_and",
-  "integer_bitor", "integer_bitxor", "integer_bitand", "integer_eq",
-  "integer_rela", "integer_shift", "integer_add", "integer_mul",
-  "integer_unary", "bytestring", "subnodes", "subnode", 0
+  "$end", "error", "$undefined", "DT_V1", "DT_PLUGIN", "DT_MEMRESERVE",
+  "DT_LSHIFT", "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND",
+  "DT_OR", "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME",
+  "DT_LITERAL", "DT_CHAR_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING",
+  "DT_LABEL", "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='",
+  "'>'", "'['", "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'",
+  "'^'", "'&'", "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept",
+  "sourcefile", "plugindecl", "memreserves", "memreserve", "devicetree",
+  "nodedef", "proplist", "propdef", "propdata", "propdataprefix",
+  "arrayprefix", "integer_prim", "integer_expr", "integer_trinary",
+  "integer_or", "integer_and", "integer_bitor", "integer_bitxor",
+  "integer_bitand", "integer_eq", "integer_rela", "integer_shift",
+  "integer_add", "integer_mul", "integer_unary", "bytestring", "subnodes",
+  "subnode", 0
 };
 #endif
 
@@ -539,36 +546,38 @@ static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,    59,    47,   123,   125,    61,
-      62,    91,    93,    40,    44,    41,    60,    63,    58,   124,
-      94,    38,    43,    45,    42,    37,   126,    33
+     275,   276,   277,   278,   279,   280,    59,    47,   123,   125,
+      61,    62,    91,    93,    40,    44,    41,    60,    63,    58,
+     124,    94,    38,    43,    45,    42,    37,   126,    33
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    48,    49,    50,    50,    51,    51,    52,    52,    52,
-      52,    53,    54,    54,    55,    55,    55,    55,    56,    56,
-      56,    56,    56,    56,    56,    57,    57,    57,    58,    58,
-      58,    58,    58,    59,    59,    59,    60,    61,    61,    62,
-      62,    63,    63,    64,    64,    65,    65,    66,    66,    67,
-      67,    67,    68,    68,    68,    68,    68,    69,    69,    69,
-      70,    70,    70,    71,    71,    71,    71,    72,    72,    72,
-      72,    73,    73,    73,    74,    74,    74,    75,    75,    75
+       0,    49,    50,    51,    51,    52,    52,    53,    53,    54,
+      54,    54,    54,    55,    56,    56,    57,    57,    57,    57,
+      58,    58,    58,    58,    58,    58,    58,    59,    59,    59,
+      60,    60,    60,    60,    60,    61,    61,    61,    62,    63,
+      63,    64,    64,    65,    65,    66,    66,    67,    67,    68,
+      68,    69,    69,    69,    70,    70,    70,    70,    70,    71,
+      71,    71,    72,    72,    72,    73,    73,    73,    73,    74,
+      74,    74,    74,    75,    75,    75,    76,    76,    76,    77,
+      77,    77
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
-       0,     2,     4,     0,     2,     4,     2,     2,     3,     3,
-       4,     5,     0,     2,     4,     2,     3,     2,     2,     3,
-       4,     2,     9,     5,     2,     0,     2,     2,     3,     1,
-       2,     2,     2,     1,     1,     3,     1,     1,     5,     1,
-       3,     1,     3,     1,     3,     1,     3,     1,     3,     1,
-       3,     3,     1,     3,     3,     3,     3,     3,     3,     1,
-       3,     3,     1,     3,     3,     3,     1,     1,     2,     2,
-       2,     0,     2,     2,     0,     2,     2,     2,     3,     2
+       0,     2,     5,     0,     2,     0,     2,     4,     2,     2,
+       3,     3,     4,     5,     0,     2,     4,     2,     3,     2,
+       2,     3,     4,     2,     9,     5,     2,     0,     2,     2,
+       3,     1,     2,     2,     2,     1,     1,     3,     1,     1,
+       5,     1,     3,     1,     3,     1,     3,     1,     3,     1,
+       3,     1,     3,     3,     1,     3,     3,     3,     3,     3,
+       3,     1,     3,     3,     1,     3,     3,     3,     1,     1,
+       2,     2,     2,     0,     2,     2,     0,     2,     2,     2,
+       3,     2
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -576,59 +585,59 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       0,     0,     0,     3,     1,     0,     0,     0,     3,    33,
-      34,     0,     0,     6,     0,     2,     4,     0,     0,     0,
-      67,     0,    36,    37,    39,    41,    43,    45,    47,    49,
-      52,    59,    62,    66,     0,    12,     7,     0,     0,     0,
-      68,    69,    70,    35,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     3,     1,     0,     5,     4,     0,     0,
+       0,     5,    35,    36,     0,     0,     8,     0,     2,     6,
+       0,     0,     0,    69,     0,    38,    39,    41,    43,    45,
+      47,    49,    51,    54,    61,    64,    68,     0,    14,     9,
+       0,     0,     0,    70,    71,    72,    37,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     5,    74,     0,     9,     8,    40,     0,
-      42,    44,    46,    48,    50,    51,    55,    56,    54,    53,
-      57,    58,    60,    61,    64,    63,    65,     0,     0,     0,
-       0,    13,     0,    74,    10,     0,     0,     0,    15,    25,
-      77,    17,    79,     0,    76,    75,    38,    16,    78,     0,
-       0,    11,    24,    14,    26,     0,    18,    27,    21,     0,
-      71,    29,     0,     0,     0,     0,    32,    31,    19,    30,
-      28,     0,    72,    73,    20,     0,    23,     0,     0,     0,
-      22
+       0,     0,     0,     0,     0,     0,     7,    76,     0,    11,
+      10,    42,     0,    44,    46,    48,    50,    52,    53,    57,
+      58,    56,    55,    59,    60,    62,    63,    66,    65,    67,
+       0,     0,     0,     0,    15,     0,    76,    12,     0,     0,
+       0,    17,    27,    79,    19,    81,     0,    78,    77,    40,
+      18,    80,     0,     0,    13,    26,    16,    28,     0,    20,
+      29,    23,     0,    73,    31,     0,     0,     0,     0,    34,
+      33,    21,    32,    30,     0,    74,    75,    22,     0,    25,
+       0,     0,     0,    24
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int8 yydefgoto[] =
+static const yytype_int16 yydefgoto[] =
 {
-      -1,     2,     7,     8,    15,    36,    64,    91,   109,   110,
-     122,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    32,    33,   125,    92,    93
+      -1,     2,     6,    10,    11,    18,    39,    67,    94,   112,
+     113,   125,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    33,    34,    35,    36,   128,    95,    96
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -78
+#define YYPACT_NINF -81
 static const yytype_int8 yypact[] =
 {
-      22,    11,    51,    10,   -78,    23,    10,     2,    10,   -78,
-     -78,    -9,    23,   -78,    30,    38,   -78,    -9,    -9,    -9,
-     -78,    35,   -78,    -6,    52,    29,    48,    49,    33,     3,
-      71,    36,     0,   -78,    64,   -78,   -78,    68,    30,    30,
-     -78,   -78,   -78,   -78,    -9,    -9,    -9,    -9,    -9,    -9,
-      -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,
-      -9,    -9,    -9,   -78,    44,    67,   -78,   -78,    52,    55,
-      29,    48,    49,    33,     3,     3,    71,    71,    71,    71,
-      36,    36,     0,     0,   -78,   -78,   -78,    78,    79,    42,
-      44,   -78,    69,    44,   -78,    -9,    73,    74,   -78,   -78,
-     -78,   -78,   -78,    75,   -78,   -78,   -78,   -78,   -78,    -7,
-      -1,   -78,   -78,   -78,   -78,    84,   -78,   -78,   -78,    63,
-     -78,   -78,    32,    66,    82,    -3,   -78,   -78,   -78,   -78,
-     -78,    46,   -78,   -78,   -78,    23,   -78,    70,    23,    72,
-     -78
+      33,    44,    63,    47,   -81,    46,     9,   -81,    22,     9,
+      55,     9,   -81,   -81,   -10,    22,   -81,    -3,    37,   -81,
+     -10,   -10,   -10,   -81,    49,   -81,    -7,    76,    50,    48,
+      52,     8,     2,    36,   -15,    -1,   -81,    65,   -81,   -81,
+      68,    -3,    -3,   -81,   -81,   -81,   -81,   -10,   -10,   -10,
+     -10,   -10,   -10,   -10,   -10,   -10,   -10,   -10,   -10,   -10,
+     -10,   -10,   -10,   -10,   -10,   -10,   -81,    51,    67,   -81,
+     -81,    76,    56,    50,    48,    52,     8,     2,     2,    36,
+      36,    36,    36,   -15,   -15,    -1,    -1,   -81,   -81,   -81,
+      79,    80,    45,    51,   -81,    69,    51,   -81,   -10,    73,
+      74,   -81,   -81,   -81,   -81,   -81,    75,   -81,   -81,   -81,
+     -81,   -81,    34,    -2,   -81,   -81,   -81,   -81,    84,   -81,
+     -81,   -81,    70,   -81,   -81,    31,    66,    83,    -6,   -81,
+     -81,   -81,   -81,   -81,    23,   -81,   -81,   -81,    22,   -81,
+      71,    22,    72,   -81
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -78,   -78,    97,   100,   -78,   -37,   -78,   -77,   -78,   -78,
-     -78,    -5,    65,    13,   -78,    76,    77,    62,    80,    83,
-      34,    20,    26,    28,   -14,   -78,    18,    24
+     -81,   -81,   -81,    96,   100,   -81,   -40,   -81,   -80,   -81,
+     -81,   -81,    -8,    62,    13,   -81,    77,    64,    78,    61,
+      82,    27,    21,    24,    25,   -17,   -81,    18,    26
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -638,59 +647,59 @@ static const yytype_int8 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-      12,    66,    67,    40,    41,    42,    44,    34,     9,    10,
-      52,    53,   115,   101,     5,   112,   104,   132,   113,   133,
-     116,   117,   118,   119,    11,     1,    60,   114,    14,   134,
-     120,    45,     6,    54,    17,   121,     3,    18,    19,    55,
-       9,    10,    50,    51,    61,    62,    84,    85,    86,     9,
-      10,     4,   100,    37,   126,   127,    11,    35,    87,    88,
-      89,    38,   128,    46,    39,    11,    90,    98,    47,    35,
-      43,    99,    76,    77,    78,    79,    56,    57,    58,    59,
-     135,   136,    80,    81,    74,    75,    82,    83,    48,    63,
-      49,    65,    94,    95,    96,    97,   124,   103,   107,   108,
-     111,   123,   130,   131,   138,    16,    13,   140,   106,    71,
-      69,   105,     0,     0,   102,     0,     0,   129,     0,     0,
-      68,     0,     0,    70,     0,     0,     0,     0,    72,     0,
-     137,     0,    73,   139
+      15,    69,    70,    43,    44,    45,    47,    37,    12,    13,
+      55,    56,   118,   104,     8,   135,   107,   136,    53,    54,
+     119,   120,   121,   122,    14,    38,    63,   137,    61,    62,
+     123,    48,     9,    57,    20,   124,     1,    21,    22,    58,
+      12,    13,    59,    60,    64,    65,    87,    88,    89,    12,
+      13,     5,   103,    40,   129,   130,    14,   115,   138,   139,
+     116,    41,   131,     4,    42,    14,    90,    91,    92,   117,
+       3,   101,     7,    38,    93,   102,    79,    80,    81,    82,
+      77,    78,    17,    83,    84,    46,    85,    86,    49,    51,
+      50,    66,    68,    97,    52,    98,    99,   100,   106,   110,
+     111,   114,   126,   133,   127,   134,   141,    19,   143,    16,
+      72,   109,    75,    73,   108,     0,     0,   132,     0,   105,
+       0,     0,     0,     0,    71,     0,     0,     0,    74,     0,
+     140,     0,     0,   142,    76
 };
 
 static const yytype_int16 yycheck[] =
 {
-       5,    38,    39,    17,    18,    19,    12,    12,    17,    18,
-       7,     8,    13,    90,     4,    22,    93,    20,    25,    22,
-      21,    22,    23,    24,    33,     3,    26,    34,    26,    32,
-      31,    37,    22,    30,    43,    36,    25,    46,    47,    36,
-      17,    18,     9,    10,    44,    45,    60,    61,    62,    17,
-      18,     0,    89,    15,    22,    23,    33,    27,    14,    15,
-      16,    23,    30,    11,    26,    33,    22,    25,    39,    27,
-      35,    29,    52,    53,    54,    55,     5,     6,    42,    43,
-      34,    35,    56,    57,    50,    51,    58,    59,    40,    25,
-      41,    23,    25,    38,    16,    16,    33,    28,    25,    25,
-      25,    17,    36,    21,    34,     8,     6,    35,    95,    47,
-      45,    93,    -1,    -1,    90,    -1,    -1,   122,    -1,    -1,
-      44,    -1,    -1,    46,    -1,    -1,    -1,    -1,    48,    -1,
-     135,    -1,    49,   138
+       8,    41,    42,    20,    21,    22,    13,    15,    18,    19,
+       8,     9,    14,    93,     5,    21,    96,    23,    10,    11,
+      22,    23,    24,    25,    34,    28,    27,    33,    43,    44,
+      32,    38,    23,    31,    44,    37,     3,    47,    48,    37,
+      18,    19,     6,     7,    45,    46,    63,    64,    65,    18,
+      19,     4,    92,    16,    23,    24,    34,    23,    35,    36,
+      26,    24,    31,     0,    27,    34,    15,    16,    17,    35,
+      26,    26,    26,    28,    23,    30,    55,    56,    57,    58,
+      53,    54,    27,    59,    60,    36,    61,    62,    12,    41,
+      40,    26,    24,    26,    42,    39,    17,    17,    29,    26,
+      26,    26,    18,    37,    34,    22,    35,    11,    36,     9,
+      48,    98,    51,    49,    96,    -1,    -1,   125,    -1,    93,
+      -1,    -1,    -1,    -1,    47,    -1,    -1,    -1,    50,    -1,
+     138,    -1,    -1,   141,    52
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,    49,    25,     0,     4,    22,    50,    51,    17,
-      18,    33,    59,    51,    26,    52,    50,    43,    46,    47,
-      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
-      69,    70,    71,    72,    59,    27,    53,    15,    23,    26,
-      72,    72,    72,    35,    12,    37,    11,    39,    40,    41,
-       9,    10,     7,     8,    30,    36,     5,     6,    42,    43,
-      26,    44,    45,    25,    54,    23,    53,    53,    63,    60,
-      64,    65,    66,    67,    68,    68,    69,    69,    69,    69,
-      70,    70,    71,    71,    72,    72,    72,    14,    15,    16,
-      22,    55,    74,    75,    25,    38,    16,    16,    25,    29,
-      53,    55,    75,    28,    55,    74,    61,    25,    25,    56,
-      57,    25,    22,    25,    34,    13,    21,    22,    23,    24,
-      31,    36,    58,    17,    33,    73,    22,    23,    30,    59,
-      36,    21,    20,    22,    32,    34,    35,    59,    34,    59,
-      35
+       0,     3,    50,    26,     0,     4,    51,    26,     5,    23,
+      52,    53,    18,    19,    34,    61,    53,    27,    54,    52,
+      44,    47,    48,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    61,    28,    55,
+      16,    24,    27,    74,    74,    74,    36,    13,    38,    12,
+      40,    41,    42,    10,    11,     8,     9,    31,    37,     6,
+       7,    43,    44,    27,    45,    46,    26,    56,    24,    55,
+      55,    65,    62,    66,    67,    68,    69,    70,    70,    71,
+      71,    71,    71,    72,    72,    73,    73,    74,    74,    74,
+      15,    16,    17,    23,    57,    76,    77,    26,    39,    17,
+      17,    26,    30,    55,    57,    77,    29,    57,    76,    63,
+      26,    26,    58,    59,    26,    23,    26,    35,    14,    22,
+      23,    24,    25,    32,    37,    60,    18,    34,    75,    23,
+      24,    31,    61,    37,    22,    21,    23,    33,    35,    36,
+      61,    35,    61,    36
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -1504,72 +1513,92 @@ yyreduce:
         case 2:
 
 /* Line 1455 of yacc.c  */
-#line 110 "dtc-parser.y"
+#line 114 "dtc-parser.y"
     {
-			the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node),
-							guess_boot_cpuid((yyvsp[(4) - (4)].node)));
+			(yyvsp[(5) - (5)].node)->is_plugin = (yyvsp[(3) - (5)].is_plugin);
+			(yyvsp[(5) - (5)].node)->is_root = 1;
+			the_boot_info = build_boot_info((yyvsp[(4) - (5)].re), (yyvsp[(5) - (5)].node),
+							guess_boot_cpuid((yyvsp[(5) - (5)].node)));
 		;}
     break;
 
   case 3:
 
 /* Line 1455 of yacc.c  */
-#line 118 "dtc-parser.y"
+#line 124 "dtc-parser.y"
     {
-			(yyval.re) = NULL;
+			(yyval.is_plugin) = 0;
 		;}
     break;
 
   case 4:
 
 /* Line 1455 of yacc.c  */
-#line 122 "dtc-parser.y"
+#line 128 "dtc-parser.y"
     {
-			(yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
+			(yyval.is_plugin) = 1;
 		;}
     break;
 
   case 5:
 
 /* Line 1455 of yacc.c  */
-#line 129 "dtc-parser.y"
+#line 135 "dtc-parser.y"
     {
-			(yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].integer), (yyvsp[(3) - (4)].integer));
+			(yyval.re) = NULL;
 		;}
     break;
 
   case 6:
 
 /* Line 1455 of yacc.c  */
-#line 133 "dtc-parser.y"
+#line 139 "dtc-parser.y"
+    {
+			(yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
+		;}
+    break;
+
+  case 7:
+
+/* Line 1455 of yacc.c  */
+#line 146 "dtc-parser.y"
+    {
+			(yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].integer), (yyvsp[(3) - (4)].integer));
+		;}
+    break;
+
+  case 8:
+
+/* Line 1455 of yacc.c  */
+#line 150 "dtc-parser.y"
     {
 			add_label(&(yyvsp[(2) - (2)].re)->labels, (yyvsp[(1) - (2)].labelref));
 			(yyval.re) = (yyvsp[(2) - (2)].re);
 		;}
     break;
 
-  case 7:
+  case 9:
 
 /* Line 1455 of yacc.c  */
-#line 141 "dtc-parser.y"
+#line 158 "dtc-parser.y"
     {
 			(yyval.node) = name_node((yyvsp[(2) - (2)].node), "");
 		;}
     break;
 
-  case 8:
+  case 10:
 
 /* Line 1455 of yacc.c  */
-#line 145 "dtc-parser.y"
+#line 162 "dtc-parser.y"
     {
 			(yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 		;}
     break;
 
-  case 9:
+  case 11:
 
 /* Line 1455 of yacc.c  */
-#line 149 "dtc-parser.y"
+#line 166 "dtc-parser.y"
     {
 			struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref));
 
@@ -1581,10 +1610,10 @@ yyreduce:
 		;}
     break;
 
-  case 10:
+  case 12:
 
 /* Line 1455 of yacc.c  */
-#line 159 "dtc-parser.y"
+#line 176 "dtc-parser.y"
     {
 			struct node *target = get_node_by_ref((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].labelref));
 
@@ -1597,110 +1626,110 @@ yyreduce:
 		;}
     break;
 
-  case 11:
+  case 13:
 
 /* Line 1455 of yacc.c  */
-#line 173 "dtc-parser.y"
+#line 190 "dtc-parser.y"
     {
 			(yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
 		;}
     break;
 
-  case 12:
+  case 14:
 
 /* Line 1455 of yacc.c  */
-#line 180 "dtc-parser.y"
+#line 197 "dtc-parser.y"
     {
 			(yyval.proplist) = NULL;
 		;}
     break;
 
-  case 13:
+  case 15:
 
 /* Line 1455 of yacc.c  */
-#line 184 "dtc-parser.y"
+#line 201 "dtc-parser.y"
     {
 			(yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
 		;}
     break;
 
-  case 14:
+  case 16:
 
 /* Line 1455 of yacc.c  */
-#line 191 "dtc-parser.y"
+#line 208 "dtc-parser.y"
     {
 			(yyval.prop) = build_property((yyvsp[(1) - (4)].propnodename), (yyvsp[(3) - (4)].data));
 		;}
     break;
 
-  case 15:
+  case 17:
 
 /* Line 1455 of yacc.c  */
-#line 195 "dtc-parser.y"
+#line 212 "dtc-parser.y"
     {
 			(yyval.prop) = build_property((yyvsp[(1) - (2)].propnodename), empty_data);
 		;}
     break;
 
-  case 16:
+  case 18:
 
 /* Line 1455 of yacc.c  */
-#line 199 "dtc-parser.y"
+#line 216 "dtc-parser.y"
     {
 			(yyval.prop) = build_property_delete((yyvsp[(2) - (3)].propnodename));
 		;}
     break;
 
-  case 17:
+  case 19:
 
 /* Line 1455 of yacc.c  */
-#line 203 "dtc-parser.y"
+#line 220 "dtc-parser.y"
     {
 			add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref));
 			(yyval.prop) = (yyvsp[(2) - (2)].prop);
 		;}
     break;
 
-  case 18:
+  case 20:
 
 /* Line 1455 of yacc.c  */
-#line 211 "dtc-parser.y"
+#line 228 "dtc-parser.y"
     {
 			(yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
 		;}
     break;
 
-  case 19:
+  case 21:
 
 /* Line 1455 of yacc.c  */
-#line 215 "dtc-parser.y"
+#line 232 "dtc-parser.y"
     {
 			(yyval.data) = data_merge((yyvsp[(1) - (3)].data), (yyvsp[(2) - (3)].array).data);
 		;}
     break;
 
-  case 20:
+  case 22:
 
 /* Line 1455 of yacc.c  */
-#line 219 "dtc-parser.y"
+#line 236 "dtc-parser.y"
     {
 			(yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
 		;}
     break;
 
-  case 21:
+  case 23:
 
 /* Line 1455 of yacc.c  */
-#line 223 "dtc-parser.y"
+#line 240 "dtc-parser.y"
     {
 			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
 		;}
     break;
 
-  case 22:
+  case 24:
 
 /* Line 1455 of yacc.c  */
-#line 227 "dtc-parser.y"
+#line 244 "dtc-parser.y"
     {
 			FILE *f = srcfile_relative_open((yyvsp[(4) - (9)].data).val, NULL);
 			struct data d;
@@ -1719,10 +1748,10 @@ yyreduce:
 		;}
     break;
 
-  case 23:
+  case 25:
 
 /* Line 1455 of yacc.c  */
-#line 244 "dtc-parser.y"
+#line 261 "dtc-parser.y"
     {
 			FILE *f = srcfile_relative_open((yyvsp[(4) - (5)].data).val, NULL);
 			struct data d = empty_data;
@@ -1734,46 +1763,46 @@ yyreduce:
 		;}
     break;
 
-  case 24:
+  case 26:
 
 /* Line 1455 of yacc.c  */
-#line 254 "dtc-parser.y"
+#line 271 "dtc-parser.y"
     {
 			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
 		;}
     break;
 
-  case 25:
+  case 27:
 
 /* Line 1455 of yacc.c  */
-#line 261 "dtc-parser.y"
+#line 278 "dtc-parser.y"
     {
 			(yyval.data) = empty_data;
 		;}
     break;
 
-  case 26:
+  case 28:
 
 /* Line 1455 of yacc.c  */
-#line 265 "dtc-parser.y"
+#line 282 "dtc-parser.y"
     {
 			(yyval.data) = (yyvsp[(1) - (2)].data);
 		;}
     break;
 
-  case 27:
+  case 29:
 
 /* Line 1455 of yacc.c  */
-#line 269 "dtc-parser.y"
+#line 286 "dtc-parser.y"
     {
 			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
 		;}
     break;
 
-  case 28:
+  case 30:
 
 /* Line 1455 of yacc.c  */
-#line 276 "dtc-parser.y"
+#line 293 "dtc-parser.y"
     {
 			(yyval.array).data = empty_data;
 			(yyval.array).bits = eval_literal((yyvsp[(2) - (3)].literal), 0, 7);
@@ -1790,20 +1819,20 @@ yyreduce:
 		;}
     break;
 
-  case 29:
+  case 31:
 
 /* Line 1455 of yacc.c  */
-#line 291 "dtc-parser.y"
+#line 308 "dtc-parser.y"
     {
 			(yyval.array).data = empty_data;
 			(yyval.array).bits = 32;
 		;}
     break;
 
-  case 30:
+  case 32:
 
 /* Line 1455 of yacc.c  */
-#line 296 "dtc-parser.y"
+#line 313 "dtc-parser.y"
     {
 			if ((yyvsp[(1) - (2)].array).bits < 64) {
 				uint64_t mask = (1ULL << (yyvsp[(1) - (2)].array).bits) - 1;
@@ -1825,10 +1854,10 @@ yyreduce:
 		;}
     break;
 
-  case 31:
+  case 33:
 
 /* Line 1455 of yacc.c  */
-#line 316 "dtc-parser.y"
+#line 333 "dtc-parser.y"
     {
 			uint64_t val = ~0ULL >> (64 - (yyvsp[(1) - (2)].array).bits);
 
@@ -1844,273 +1873,273 @@ yyreduce:
 		;}
     break;
 
-  case 32:
+  case 34:
 
 /* Line 1455 of yacc.c  */
-#line 330 "dtc-parser.y"
+#line 347 "dtc-parser.y"
     {
 			(yyval.array).data = data_add_marker((yyvsp[(1) - (2)].array).data, LABEL, (yyvsp[(2) - (2)].labelref));
 		;}
     break;
 
-  case 33:
+  case 35:
 
 /* Line 1455 of yacc.c  */
-#line 337 "dtc-parser.y"
+#line 354 "dtc-parser.y"
     {
 			(yyval.integer) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
 		;}
     break;
 
-  case 34:
+  case 36:
 
 /* Line 1455 of yacc.c  */
-#line 341 "dtc-parser.y"
+#line 358 "dtc-parser.y"
     {
 			(yyval.integer) = eval_char_literal((yyvsp[(1) - (1)].literal));
 		;}
     break;
 
-  case 35:
+  case 37:
 
 /* Line 1455 of yacc.c  */
-#line 345 "dtc-parser.y"
+#line 362 "dtc-parser.y"
     {
 			(yyval.integer) = (yyvsp[(2) - (3)].integer);
 		;}
     break;
 
-  case 38:
+  case 40:
 
 /* Line 1455 of yacc.c  */
-#line 356 "dtc-parser.y"
+#line 373 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (5)].integer) ? (yyvsp[(3) - (5)].integer) : (yyvsp[(5) - (5)].integer); ;}
     break;
 
-  case 40:
+  case 42:
 
 /* Line 1455 of yacc.c  */
-#line 361 "dtc-parser.y"
+#line 378 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) || (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 42:
+  case 44:
 
 /* Line 1455 of yacc.c  */
-#line 366 "dtc-parser.y"
+#line 383 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) && (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 44:
+  case 46:
 
 /* Line 1455 of yacc.c  */
-#line 371 "dtc-parser.y"
+#line 388 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) | (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 46:
+  case 48:
 
 /* Line 1455 of yacc.c  */
-#line 376 "dtc-parser.y"
+#line 393 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) ^ (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 48:
+  case 50:
 
 /* Line 1455 of yacc.c  */
-#line 381 "dtc-parser.y"
+#line 398 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) & (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 50:
+  case 52:
 
 /* Line 1455 of yacc.c  */
-#line 386 "dtc-parser.y"
+#line 403 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) == (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 51:
+  case 53:
 
 /* Line 1455 of yacc.c  */
-#line 387 "dtc-parser.y"
+#line 404 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) != (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 53:
+  case 55:
 
 /* Line 1455 of yacc.c  */
-#line 392 "dtc-parser.y"
+#line 409 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) < (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 54:
+  case 56:
 
 /* Line 1455 of yacc.c  */
-#line 393 "dtc-parser.y"
+#line 410 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) > (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 55:
+  case 57:
 
 /* Line 1455 of yacc.c  */
-#line 394 "dtc-parser.y"
+#line 411 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) <= (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 56:
+  case 58:
 
 /* Line 1455 of yacc.c  */
-#line 395 "dtc-parser.y"
+#line 412 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) >= (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 57:
+  case 59:
 
 /* Line 1455 of yacc.c  */
-#line 399 "dtc-parser.y"
+#line 416 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) << (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 58:
+  case 60:
 
 /* Line 1455 of yacc.c  */
-#line 400 "dtc-parser.y"
+#line 417 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) >> (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 60:
+  case 62:
 
 /* Line 1455 of yacc.c  */
-#line 405 "dtc-parser.y"
+#line 422 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) + (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 61:
+  case 63:
 
 /* Line 1455 of yacc.c  */
-#line 406 "dtc-parser.y"
+#line 423 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) - (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 63:
+  case 65:
 
 /* Line 1455 of yacc.c  */
-#line 411 "dtc-parser.y"
+#line 428 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) * (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 64:
+  case 66:
 
 /* Line 1455 of yacc.c  */
-#line 412 "dtc-parser.y"
+#line 429 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) / (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 65:
+  case 67:
 
 /* Line 1455 of yacc.c  */
-#line 413 "dtc-parser.y"
+#line 430 "dtc-parser.y"
     { (yyval.integer) = (yyvsp[(1) - (3)].integer) % (yyvsp[(3) - (3)].integer); ;}
     break;
 
-  case 68:
+  case 70:
 
 /* Line 1455 of yacc.c  */
-#line 419 "dtc-parser.y"
+#line 436 "dtc-parser.y"
     { (yyval.integer) = -(yyvsp[(2) - (2)].integer); ;}
     break;
 
-  case 69:
+  case 71:
 
 /* Line 1455 of yacc.c  */
-#line 420 "dtc-parser.y"
+#line 437 "dtc-parser.y"
     { (yyval.integer) = ~(yyvsp[(2) - (2)].integer); ;}
     break;
 
-  case 70:
+  case 72:
 
 /* Line 1455 of yacc.c  */
-#line 421 "dtc-parser.y"
+#line 438 "dtc-parser.y"
     { (yyval.integer) = !(yyvsp[(2) - (2)].integer); ;}
     break;
 
-  case 71:
+  case 73:
 
 /* Line 1455 of yacc.c  */
-#line 426 "dtc-parser.y"
+#line 443 "dtc-parser.y"
     {
 			(yyval.data) = empty_data;
 		;}
     break;
 
-  case 72:
+  case 74:
 
 /* Line 1455 of yacc.c  */
-#line 430 "dtc-parser.y"
+#line 447 "dtc-parser.y"
     {
 			(yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
 		;}
     break;
 
-  case 73:
+  case 75:
 
 /* Line 1455 of yacc.c  */
-#line 434 "dtc-parser.y"
+#line 451 "dtc-parser.y"
     {
 			(yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
 		;}
     break;
 
-  case 74:
+  case 76:
 
 /* Line 1455 of yacc.c  */
-#line 441 "dtc-parser.y"
+#line 458 "dtc-parser.y"
     {
 			(yyval.nodelist) = NULL;
 		;}
     break;
 
-  case 75:
+  case 77:
 
 /* Line 1455 of yacc.c  */
-#line 445 "dtc-parser.y"
+#line 462 "dtc-parser.y"
     {
 			(yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
 		;}
     break;
 
-  case 76:
+  case 78:
 
 /* Line 1455 of yacc.c  */
-#line 449 "dtc-parser.y"
+#line 466 "dtc-parser.y"
     {
 			print_error("syntax error: properties must precede subnodes");
 			YYERROR;
 		;}
     break;
 
-  case 77:
+  case 79:
 
 /* Line 1455 of yacc.c  */
-#line 457 "dtc-parser.y"
+#line 474 "dtc-parser.y"
     {
 			(yyval.node) = name_node((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].propnodename));
 		;}
     break;
 
-  case 78:
+  case 80:
 
 /* Line 1455 of yacc.c  */
-#line 461 "dtc-parser.y"
+#line 478 "dtc-parser.y"
     {
 			(yyval.node) = name_node(build_node_delete(), (yyvsp[(2) - (3)].propnodename));
 		;}
     break;
 
-  case 79:
+  case 81:
 
 /* Line 1455 of yacc.c  */
-#line 465 "dtc-parser.y"
+#line 482 "dtc-parser.y"
     {
 			add_label(&(yyvsp[(2) - (2)].node)->labels, (yyvsp[(1) - (2)].labelref));
 			(yyval.node) = (yyvsp[(2) - (2)].node);
@@ -2120,7 +2149,7 @@ yyreduce:
 
 
 /* Line 1455 of yacc.c  */
-#line 2124 "dtc-parser.tab.c"
+#line 2153 "dtc-parser.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2332,7 +2361,7 @@ yyreturn:
 
 
 /* Line 1675 of yacc.c  */
-#line 471 "dtc-parser.y"
+#line 488 "dtc-parser.y"
 
 
 void print_error(char const *fmt, ...)
diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped
index 9d2dce4..e4dfadf 100644
--- a/scripts/dtc/dtc-parser.tab.h_shipped
+++ b/scripts/dtc/dtc-parser.tab.h_shipped
@@ -40,27 +40,28 @@
       know about them.  */
    enum yytokentype {
      DT_V1 = 258,
-     DT_MEMRESERVE = 259,
-     DT_LSHIFT = 260,
-     DT_RSHIFT = 261,
-     DT_LE = 262,
-     DT_GE = 263,
-     DT_EQ = 264,
-     DT_NE = 265,
-     DT_AND = 266,
-     DT_OR = 267,
-     DT_BITS = 268,
-     DT_DEL_PROP = 269,
-     DT_DEL_NODE = 270,
-     DT_PROPNODENAME = 271,
-     DT_LITERAL = 272,
-     DT_CHAR_LITERAL = 273,
-     DT_BASE = 274,
-     DT_BYTE = 275,
-     DT_STRING = 276,
-     DT_LABEL = 277,
-     DT_REF = 278,
-     DT_INCBIN = 279
+     DT_PLUGIN = 259,
+     DT_MEMRESERVE = 260,
+     DT_LSHIFT = 261,
+     DT_RSHIFT = 262,
+     DT_LE = 263,
+     DT_GE = 264,
+     DT_EQ = 265,
+     DT_NE = 266,
+     DT_AND = 267,
+     DT_OR = 268,
+     DT_BITS = 269,
+     DT_DEL_PROP = 270,
+     DT_DEL_NODE = 271,
+     DT_PROPNODENAME = 272,
+     DT_LITERAL = 273,
+     DT_CHAR_LITERAL = 274,
+     DT_BASE = 275,
+     DT_BYTE = 276,
+     DT_STRING = 277,
+     DT_LABEL = 278,
+     DT_REF = 279,
+     DT_INCBIN = 280
    };
 #endif
 
@@ -71,7 +72,7 @@ typedef union YYSTYPE
 {
 
 /* Line 1676 of yacc.c  */
-#line 40 "dtc-parser.y"
+#line 41 "dtc-parser.y"
 
 	char *propnodename;
 	char *literal;
@@ -91,11 +92,12 @@ typedef union YYSTYPE
 	struct node *nodelist;
 	struct reserve_info *re;
 	uint64_t integer;
+	int is_plugin;
 
 
 
 /* Line 1676 of yacc.c  */
-#line 99 "dtc-parser.tab.h"
+#line 101 "dtc-parser.tab.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
index f412460..e444acf 100644
--- a/scripts/dtc/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
@@ -20,6 +20,7 @@
 
 %{
 #include <stdio.h>
+#include <inttypes.h>
 
 #include "dtc.h"
 #include "srcpos.h"
@@ -56,9 +57,11 @@ static unsigned char eval_char_literal(const char *s);
 	struct node *nodelist;
 	struct reserve_info *re;
 	uint64_t integer;
+	int is_plugin;
 }
 
 %token DT_V1
+%token DT_PLUGIN
 %token DT_MEMRESERVE
 %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
 %token DT_BITS
@@ -76,6 +79,7 @@ static unsigned char eval_char_literal(const char *s);
 
 %type <data> propdata
 %type <data> propdataprefix
+%type <is_plugin> plugindecl
 %type <re> memreserve
 %type <re> memreserves
 %type <array> arrayprefix
@@ -106,10 +110,23 @@ static unsigned char eval_char_literal(const char *s);
 %%
 
 sourcefile:
-	  DT_V1 ';' memreserves devicetree
+	  DT_V1 ';' plugindecl memreserves devicetree
 		{
-			the_boot_info = build_boot_info($3, $4,
-							guess_boot_cpuid($4));
+			$5->is_plugin = $3;
+			$5->is_root = 1;
+			the_boot_info = build_boot_info($4, $5,
+							guess_boot_cpuid($5));
+		}
+	;
+
+plugindecl:
+	/* empty */
+		{
+			$$ = 0;
+		}
+	| DT_PLUGIN ';'
+		{
+			$$ = 1;
 		}
 	;
 
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index a375683..30d9607 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -31,6 +31,7 @@ int reservenum;		/* Number of memory reservation slots */
 int minsize;		/* Minimum blob size */
 int padsize;		/* Additional padding to blob */
 int phandle_format = PHANDLE_BOTH;	/* Use linux,phandle or phandle properties */
+int symbol_fixup_support = 0;
 
 static void fill_fullpaths(struct node *tree, const char *prefix)
 {
@@ -96,6 +97,8 @@ static void  __attribute__ ((noreturn)) usage(void)
 	fprintf(stderr, "\t-W [no-]<checkname>\n");
 	fprintf(stderr, "\t-E [no-]<checkname>\n");
 	fprintf(stderr, "\t\t\tenable or disable warnings and errors\n");
+	fprintf(stderr, "\t-@\n");
+	fprintf(stderr, "\t\tSymbols and Fixups support\n");
 	exit(3);
 }
 
@@ -118,7 +121,7 @@ int main(int argc, char *argv[])
 	minsize    = 0;
 	padsize    = 0;
 
-	while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:"))
+	while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:@"))
 			!= EOF) {
 		switch (opt) {
 		case 'I':
@@ -183,7 +186,9 @@ int main(int argc, char *argv[])
 		case 'E':
 			parse_checks_option(false, true, optarg);
 			break;
-
+		case '@':
+			symbol_fixup_support = 1;
+			break;
 		case 'h':
 		default:
 			usage();
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index 3e42a07..0c8ecf6 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -54,6 +54,7 @@ extern int reservenum;		/* Number of memory reservation slots */
 extern int minsize;		/* Minimum blob size */
 extern int padsize;		/* Additional padding to blob */
 extern int phandle_format;	/* Use linux,phandle or phandle properties */
+extern int symbol_fixup_support;/* enable symbols & fixup support */
 
 #define PHANDLE_LEGACY	0x1
 #define PHANDLE_EPAPR	0x2
@@ -133,6 +134,25 @@ struct label {
 	struct label *next;
 };
 
+struct fixup_entry {
+	int offset;
+	struct node *node;
+	struct property *prop;
+	struct fixup_entry *next;
+};
+
+struct fixup {
+	char *ref;
+	struct fixup_entry *entries;
+	struct fixup *next;
+};
+
+struct symbol {
+	struct label *label;
+	struct node *node;
+	struct symbol *next;
+};
+
 struct property {
 	int deleted;
 	char *name;
@@ -159,6 +179,12 @@ struct node {
 	int addr_cells, size_cells;
 
 	struct label *labels;
+
+	int is_root;
+	int is_plugin;
+	struct fixup *fixups;
+	struct symbol *symbols;
+	struct fixup_entry *local_fixups;
 };
 
 #define for_each_label_withdel(l0, l) \
@@ -182,6 +208,18 @@ struct node {
 	for_each_child_withdel(n, c) \
 		if (!(c)->deleted)
 
+#define for_each_fixup(n, f) \
+	for ((f) = (n)->fixups; (f); (f) = (f)->next)
+
+#define for_each_fixup_entry(f, fe) \
+	for ((fe) = (f)->entries; (fe); (fe) = (fe)->next)
+
+#define for_each_symbol(n, s) \
+	for ((s) = (n)->symbols; (s); (s) = (s)->next)
+
+#define for_each_local_fixup_entry(n, fe) \
+	for ((fe) = (n)->local_fixups; (fe); (fe) = (fe)->next)
+
 void add_label(struct label **labels, char *label);
 void delete_labels(struct label **labels);
 
diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c
index 207a46d..d4fa6d7 100644
--- a/scripts/dtc/fdtdump.c
+++ b/scripts/dtc/fdtdump.c
@@ -21,13 +21,23 @@ static void print_data(const char *data, int len)
 {
 	int i;
 	const char *p = data;
+	const char *s;
 
 	/* no data, don't print */
 	if (len == 0)
 		return;
 
 	if (util_is_printable_string(data, len)) {
-		printf(" = \"%s\"", (const char *)data);
+		printf(" = ");
+
+		s = data;
+		do {
+			printf("\"%s\"", s);
+			s += strlen(s) + 1;
+			if (s < data + len)
+				printf(", ");
+		} while (s < data + len);
+
 	} else if ((len % 4) == 0) {
 		printf(" = <");
 		for (i = 0; i < len; i += 4)
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
index 665dad7..6237715 100644
--- a/scripts/dtc/flattree.c
+++ b/scripts/dtc/flattree.c
@@ -262,6 +262,12 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
 	struct property *prop;
 	struct node *child;
 	int seen_name_prop = 0;
+	struct symbol *sym;
+	struct fixup *f;
+	struct fixup_entry *fe;
+	char *name, *s;
+	const char *fullpath;
+	int namesz, nameoff, vallen;
 
 	if (tree->deleted)
 		return;
@@ -310,6 +316,139 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
 		flatten_tree(child, emit, etarget, strbuf, vi);
 	}
 
+	if (!symbol_fixup_support)
+		goto no_symbols;
+
+	/* add the symbol nodes (if any) */
+	if (tree->symbols) {
+
+		emit->beginnode(etarget, NULL);
+		emit->string(etarget, "__symbols__", 0);
+		emit->align(etarget, sizeof(cell_t));
+
+		for_each_symbol(tree, sym) {
+
+			vallen = strlen(sym->node->fullpath);
+
+			nameoff = stringtable_insert(strbuf, sym->label->label);
+
+			emit->property(etarget, NULL);
+			emit->cell(etarget, vallen + 1);
+			emit->cell(etarget, nameoff);
+
+			if ((vi->flags & FTF_VARALIGN) && vallen >= 8)
+				emit->align(etarget, 8);
+
+			emit->string(etarget, sym->node->fullpath,
+					strlen(sym->node->fullpath));
+			emit->align(etarget, sizeof(cell_t));
+		}
+
+		emit->endnode(etarget, NULL);
+	}
+
+	/* add the fixup nodes */
+	if (tree->fixups) {
+
+		/* emit the external fixups */
+		emit->beginnode(etarget, NULL);
+		emit->string(etarget, "__fixups__", 0);
+		emit->align(etarget, sizeof(cell_t));
+
+		for_each_fixup(tree, f) {
+
+			namesz = 0;
+			for_each_fixup_entry(f, fe) {
+				fullpath = fe->node->fullpath;
+				if (fullpath[0] == '\0')
+					fullpath = "/";
+				namesz += strlen(fullpath) + 1;
+			      	namesz += strlen(fe->prop->name) + 1;
+				namesz += 32;	/* space for :<number> + '\0' */
+			}
+
+			name = xmalloc(namesz);
+
+			s = name;
+			for_each_fixup_entry(f, fe) {
+				fullpath = fe->node->fullpath;
+				if (fullpath[0] == '\0')
+					fullpath = "/";
+				snprintf(s, name + namesz - s, "%s:%s:%d",
+						fullpath,
+						fe->prop->name, fe->offset);
+				s += strlen(s) + 1;
+			}
+
+			nameoff = stringtable_insert(strbuf, f->ref);
+			vallen = s - name - 1;
+
+			emit->property(etarget, NULL);
+			emit->cell(etarget, vallen + 1);
+			emit->cell(etarget, nameoff);
+
+			if ((vi->flags & FTF_VARALIGN) && vallen >= 8)
+				emit->align(etarget, 8);
+
+			emit->string(etarget, name, vallen);
+			emit->align(etarget, sizeof(cell_t));
+
+			free(name);
+		}
+
+		emit->endnode(etarget, tree->labels);
+	}
+
+	/* add the local fixup property */
+	if (tree->local_fixups) {
+
+		/* emit the external fixups */
+		emit->beginnode(etarget, NULL);
+		emit->string(etarget, "__local_fixups__", 0);
+		emit->align(etarget, sizeof(cell_t));
+
+		namesz = 0;
+		for_each_local_fixup_entry(tree, fe) {
+			fullpath = fe->node->fullpath;
+			if (fullpath[0] == '\0')
+				fullpath = "/";
+			namesz += strlen(fullpath) + 1;
+			namesz += strlen(fe->prop->name) + 1;
+			namesz += 32;	/* space for :<number> + '\0' */
+		}
+
+		name = xmalloc(namesz);
+
+		s = name;
+		for_each_local_fixup_entry(tree, fe) {
+			fullpath = fe->node->fullpath;
+			if (fullpath[0] == '\0')
+				fullpath = "/";
+			snprintf(s, name + namesz - s, "%s:%s:%d",
+					fullpath, fe->prop->name,
+					fe->offset);
+			s += strlen(s) + 1;
+		}
+
+		nameoff = stringtable_insert(strbuf, "fixup");
+		vallen = s - name - 1;
+
+		emit->property(etarget, NULL);
+		emit->cell(etarget, vallen + 1);
+		emit->cell(etarget, nameoff);
+
+		if ((vi->flags & FTF_VARALIGN) && vallen >= 8)
+			emit->align(etarget, 8);
+
+		emit->string(etarget, name, vallen);
+		emit->align(etarget, sizeof(cell_t));
+
+		free(name);
+
+		emit->endnode(etarget, tree->labels);
+	}
+
+no_symbols:
 	emit->endnode(etarget, tree->labels);
 }
 
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
index 2422c34..45f186b 100644
--- a/scripts/dtc/util.c
+++ b/scripts/dtc/util.c
@@ -72,7 +72,7 @@ char *join_path(const char *path, const char *name)
 int util_is_printable_string(const void *data, int len)
 {
 	const char *s = data;
-	const char *ss;
+	const char *ss, *se;
 
 	/* zero length is not */
 	if (len == 0)
@@ -82,13 +82,19 @@ int util_is_printable_string(const void *data, int len)
 	if (s[len - 1] != '\0')
 		return 0;
 
-	ss = s;
-	while (*s && isprint(*s))
-		s++;
+	se = s + len;
 
-	/* not zero, or not done yet */
-	if (*s != '\0' || (s + 1 - ss) < len)
-		return 0;
+	while (s < se) {
+		ss = s;
+		while (s < se && *s && isprint(*s))
+			s++;
+
+		/* not zero, or not done yet */
+		if (*s != '\0' || s == ss)
+			return 0;
+
+		s++;
+	}
 
 	return 1;
 }
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index acb8650..a5f197b 100644
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -25,44 +25,8 @@ create_package() {
 	chown -R root:root "$pdir"
 	chmod -R go-w "$pdir"
 
-	# Attempt to find the correct Debian architecture
-	local forcearch="" debarch=""
-	case "$UTS_MACHINE" in
-	i386|ia64|alpha)
-		debarch="$UTS_MACHINE" ;;
-	x86_64)
-		debarch=amd64 ;;
-	sparc*)
-		debarch=sparc ;;
-	s390*)
-		debarch=s390 ;;
-	ppc*)
-		debarch=powerpc ;;
-	parisc*)
-		debarch=hppa ;;
-	mips*)
-		debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y .config && echo el) ;;
-	arm*)
-		debarch=arm$(grep -q CONFIG_AEABI=y .config && echo el) ;;
-	*)
-		echo "" >&2
-		echo "** ** **  WARNING  ** ** **" >&2
-		echo "" >&2
-		echo "Your architecture doesn't have it's equivalent" >&2
-		echo "Debian userspace architecture defined!" >&2
-		echo "Falling back to using your current userspace instead!" >&2
-		echo "Please add support for $UTS_MACHINE to ${0} ..." >&2
-		echo "" >&2
-	esac
-	if [ -n "$KBUILD_DEBARCH" ] ; then
-		debarch="$KBUILD_DEBARCH"
-	fi
-	if [ -n "$debarch" ] ; then
-		forcearch="-DArchitecture=$debarch"
-	fi
-
 	# Create the package
-	dpkg-gencontrol -isp $forcearch -p$pname -P"$pdir"
+	dpkg-gencontrol -p$pname -P"$pdir"
 	dpkg --build "$pdir" ..
 }
 
@@ -83,6 +47,38 @@ fwpackagename=linux-firmware-image
 kernel_headers_packagename=linux-headers-$version
 libc_headers_packagename=linux-libc-dev
 
+# Attempt to find the correct Debian architecture
+case "$UTS_MACHINE" in
+i386|ia64|alpha)
+	debarch="$UTS_MACHINE" ;;
+x86_64)
+	debarch=amd64 ;;
+sparc*)
+	debarch=sparc ;;
+s390*)
+	debarch=s390 ;;
+ppc*)
+	debarch=powerpc ;;
+parisc*)
+	debarch=hppa ;;
+mips*)
+	debarch=mips$(grep -q CPU_LITTLE_ENDIAN=y .config && echo el) ;;
+arm*)
+	debarch=arm$(grep -q CONFIG_AEABI=y .config && echo el) ;;
+*)
+	echo "" >&2
+	echo "** ** **  WARNING  ** ** **" >&2
+	echo "" >&2
+	echo "Your architecture doesn't have it's equivalent" >&2
+	echo "Debian userspace architecture defined!" >&2
+	echo "Falling back to using your current userspace instead!" >&2
+	echo "Please add support for $UTS_MACHINE to ${0} ..." >&2
+	echo "" >&2
+esac
+if [ -n "$KBUILD_DEBARCH" ] ; then
+	debarch="$KBUILD_DEBARCH"
+fi
+
 if [ "$ARCH" = "um" ] ; then
 	packagename=user-mode-linux-$version
 fi
@@ -234,8 +230,8 @@ else
 Package: $packagename
 Provides: linux-image, linux-image-2.6, linux-modules-$version
 Suggests: $fwpackagename
-Architecture: any
-Description: Linux kernel, version $version
+Architecture: $debarch
+Description: Linux kernel, version $version on $debarch
  This package contains the Linux kernel, modules and corresponding other
  files, version: $version.
 EOF
@@ -252,15 +248,14 @@ mkdir -p "$destdir"
 (cd $objtree; tar -c -f - -T "$objtree/debian/hdrobjfiles") | (cd $destdir; tar -xf -)
 ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build"
 rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
-arch=$(dpkg --print-architecture)
 
 cat <<EOF >> debian/control
 
 Package: $kernel_headers_packagename
+Architecture: $debarch
 Provides: linux-headers, linux-headers-2.6
-Architecture: $arch
-Description: Linux kernel headers for $KERNELRELEASE on $arch
- This package provides kernel header files for $KERNELRELEASE on $arch
+Description: Linux kernel headers for $KERNELRELEASE on $debarch
+ This package provides kernel header files for $KERNELRELEASE on $debarch
  .
  This is useful for people who need to build external modules
 EOF
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 9e11a14..cfeb3a0 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -6,6 +6,14 @@ config SND_DAVINCI_SOC
 	  the DAVINCI AC97 or I2S interface. You will also need
 	  to select the audio interfaces to support below.
 
+config SND_AM33XX_SOC
+	tristate "SoC Audio for the AM33XX chip"
+	depends on SOC_AM33XX
+	select SND_SOC_TLV320AIC3X
+	help
+	  Say Y or M if you want to add support for SoC audio on AM33xx
+	  boards using McASP and TLV320AIC3X codec.
+
 config SND_DAVINCI_SOC_I2S
 	tristate
 
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index a93679d..3e07a53 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -5,8 +5,10 @@ snd-soc-davinci-mcasp-objs:= davinci-mcasp.o
 snd-soc-davinci-vcif-objs:= davinci-vcif.o
 
 obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
+obj-$(CONFIG_SND_AM33XX_SOC) += snd-soc-davinci.o
 obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
 obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o
+obj-$(CONFIG_SND_AM33XX_SOC) += snd-soc-davinci-mcasp.o
 obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += snd-soc-davinci-vcif.o
 
 # DAVINCI Machine Support
@@ -14,6 +16,7 @@ snd-soc-evm-objs := davinci-evm.o
 snd-soc-sffsdr-objs := davinci-sffsdr.o
 
 obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
+obj-$(CONFIG_SND_AM33XX_SOC) += snd-soc-evm.o
 obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o
 obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o
 obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index d55e647..7a7fc47 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -14,7 +14,9 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/platform_data/edma.h>
 #include <linux/i2c.h>
+#include <linux/of_platform.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
@@ -22,10 +24,15 @@
 #include <asm/dma.h>
 #include <asm/mach-types.h>
 
+#include <linux/edma.h>
+
 #include "davinci-pcm.h"
 #include "davinci-i2s.h"
 #include "davinci-mcasp.h"
 
+#include <linux/of_gpio.h>
+
+
 #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
 		SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
 static int evm_hw_params(struct snd_pcm_substream *substream,
@@ -34,27 +41,38 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_card *soc_card = codec->card;
+	struct device_node *np = soc_card->dev->of_node;
 	int ret = 0;
 	unsigned sysclk;
 
-	/* ASP1 on DM355 EVM is clocked by an external oscillator */
-	if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() ||
-	    machine_is_davinci_dm365_evm())
-		sysclk = 27000000;
-
-	/* ASP0 in DM6446 EVM is clocked by U55, as configured by
-	 * board-dm644x-evm.c using GPIOs from U18.  There are six
-	 * options; here we "know" we use a 48 KHz sample rate.
-	 */
-	else if (machine_is_davinci_evm())
-		sysclk = 12288000;
-
-	else if (machine_is_davinci_da830_evm() ||
-				machine_is_davinci_da850_evm())
-		sysclk = 24576000;
-
-	else
-		return -EINVAL;
+	if (np) {
+		ret = of_property_read_u32(np, "ti,codec-clock-rate", &sysclk);
+		if (ret < 0)
+			return ret;
+	} else {
+		/* ASP1 on DM355 EVM is clocked by an external oscillator */
+		if (machine_is_davinci_dm355_evm() ||
+			machine_is_davinci_dm6467_evm() ||
+			machine_is_davinci_dm365_evm())
+			sysclk = 27000000;
+
+		/*
+		 * ASP0 in DM6446 EVM is clocked by U55, as configured by
+		 * board-dm644x-evm.c using GPIOs from U18.  There are six
+		 * options; here we "know" we use a 48 KHz sample rate.
+		 */
+		else if (machine_is_davinci_evm())
+			sysclk = 12288000;
+
+		else if (machine_is_davinci_da830_evm() ||
+					machine_is_davinci_da850_evm())
+			sysclk = 24576000;
+
+		else
+			return -EINVAL;
+	}
 
 	/* set codec DAI configuration */
 	ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT);
@@ -132,13 +150,22 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct device_node *np = codec->card->dev->of_node;
+	int ret;
 
 	/* Add davinci-evm specific widgets */
 	snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
 				  ARRAY_SIZE(aic3x_dapm_widgets));
 
-	/* Set up davinci-evm specific audio path audio_map */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+	if (np) {
+		ret = snd_soc_of_parse_audio_routing(codec->card,
+							"ti,audio-routing");
+		if (ret)
+			return ret;
+	} else {
+		/* Set up davinci-evm specific audio path audio_map */
+		snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+	}
 
 	/* not connected */
 	snd_soc_dapm_disable_pin(dapm, "MONO_LOUT");
@@ -287,6 +314,139 @@ static struct snd_soc_card da850_snd_soc_card = {
 	.num_links = 1,
 };
 
+
+#if defined(CONFIG_OF)
+
+enum {
+	MACHINE_VERSION_1 = 0,	/* DM365 with Voice Codec */
+	MACHINE_VERSION_2,	/* DM365/DA8xx/OMAPL1x/AM33xx */
+	MACHINE_VERSION_3,	/* AM33xx BeagleBone Black */
+};
+
+static const struct of_device_id davinci_evm_dt_ids[] = {
+	{
+		.compatible = "ti,dm365-voice-codec-audio",
+		.data = (void *)MACHINE_VERSION_1,
+	},
+	{
+		.compatible = "ti,da830-evm-audio",
+		.data = (void *)MACHINE_VERSION_2,
+	},
+	{
+		.compatible = "ti,am33xx-beaglebone-black",
+		.data = (void *)MACHINE_VERSION_3,
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, davinci_mcasp_dt_ids);
+
+/*
+ * This struct is just used as place holder. It will be filled with
+ * data from dt node
+ */
+static struct snd_soc_dai_link evm_dai = {
+	.name		= "TLV320AIC3X",
+	.stream_name	= "AIC3X",
+	.codec_dai_name	= "tlv320aic3x-hifi",
+};
+
+/* davinci evm audio machine driver */
+static struct snd_soc_card evm_soc_card = {
+	.owner = THIS_MODULE,
+	.dai_link = &evm_dai,
+	.num_links = 1,
+};
+
+static int davinci_evm_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *match =
+		of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
+	u32 machine_ver, clk_gpio;
+	int ret = 0;
+
+	machine_ver = (u32)match->data;
+	switch (machine_ver) {
+	case MACHINE_VERSION_1:
+		evm_dai.name		= "Voice Codec - CQ93VC";
+		evm_dai.stream_name	= "CQ93";
+		evm_dai.codec_dai_name	= "cq93vc-hifi";
+		break;
+	case MACHINE_VERSION_2:
+		evm_dai.ops = &evm_ops;
+		evm_dai.init = evm_aic3x_init;
+		break;
+	case MACHINE_VERSION_3:
+		evm_dai.name		= "NXP TDA HDMI Chip";
+		evm_dai.stream_name	= "HDMI";
+		evm_dai.codec_dai_name	= "nxp-hdmi-hifi";
+
+		/* 
+		 * Move GPIO handling out of the probe, if probe gets 
+		 * deferred, the gpio will have been claimed on previous
+		 * probe and will fail on the second and susequent probes 
+		 */
+		clk_gpio = of_get_named_gpio(np, "mcasp_clock_enable", 0);
+		if (clk_gpio < 0) {
+		  dev_err(&pdev->dev, "failed to find mcasp_clock enable GPIO!\n");
+		  return -EINVAL;
+		}
+		ret = gpio_request_one(clk_gpio, GPIOF_OUT_INIT_HIGH,
+				       "McASP Clock Enable Pin");
+		if (ret < 0) {
+		  dev_err(&pdev->dev, "Failed to claim McASP Clock Enable pin\n");
+		  return -EINVAL;
+		}
+		gpio_set_value(clk_gpio, 1);
+		evm_dai.dai_fmt = SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF;
+		break;
+	  
+	}
+	
+
+	evm_dai.codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0);
+	if (!evm_dai.codec_of_node)
+		return -EINVAL;
+
+	evm_dai.cpu_of_node = of_parse_phandle(np,
+						"ti,mcasp-controller", 0);
+	if (!evm_dai.cpu_of_node)
+		return -EINVAL;
+
+	evm_dai.platform_of_node = evm_dai.cpu_of_node;
+
+	evm_soc_card.dev = &pdev->dev;
+	ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model");
+	if (ret)
+		return ret;
+
+	ret = snd_soc_register_card(&evm_soc_card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+	} 
+	return ret;
+}
+
+static int davinci_evm_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static struct platform_driver davinci_evm_driver = {
+	.probe		= davinci_evm_probe,
+	.remove		= davinci_evm_remove,
+	.driver		= {
+		.name	= "davinci_evm",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(davinci_evm_dt_ids),
+	},
+};
+#endif
+
 static struct platform_device *evm_snd_device;
 
 static int __init evm_init(void)
@@ -295,6 +455,16 @@ static int __init evm_init(void)
 	int index;
 	int ret;
 
+#if defined(CONFIG_OF)
+	/*
+	 * If dtb is there, the devices will be created dynamically.
+	 * Only register platfrom driver structure.
+	 */
+	if (of_have_populated_dt()) {
+	  return platform_driver_register(&davinci_evm_driver);
+	}
+#endif
+
 	if (machine_is_davinci_evm()) {
 		evm_snd_dev_data = &dm6446_snd_soc_card_evm;
 		index = 0;
@@ -313,8 +483,9 @@ static int __init evm_init(void)
 	} else if (machine_is_davinci_da850_evm()) {
 		evm_snd_dev_data = &da850_snd_soc_card;
 		index = 0;
-	} else
+	} else {
 		return -EINVAL;
+	}
 
 	evm_snd_device = platform_device_alloc("soc-audio", index);
 	if (!evm_snd_device)
@@ -330,6 +501,13 @@ static int __init evm_init(void)
 
 static void __exit evm_exit(void)
 {
+#if defined(CONFIG_OF)
+	if (of_have_populated_dt()) {
+		platform_driver_unregister(&davinci_evm_driver);
+		return;
+	}
+#endif
+
 	platform_device_unregister(evm_snd_device);
 }
 
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 55e2bf6..bef4e72 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -25,6 +25,7 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -497,13 +498,16 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBS_CFS:
 		/* codec is clock and frame slave */
-		mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+	  	mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE | ACLKXDIV(7));
+	  	mcasp_set_bits(base + DAVINCI_MCASP_AHCLKXCTL_REG,  AHCLKXDIV(0));
+	  	mcasp_clr_bits(base + DAVINCI_MCASP_AHCLKXCTL_REG,  AHCLKXE);
 		mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
 
 		mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
 		mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
 		mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, ACLKX | AFSX);
+		mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
 		break;
 	case SND_SOC_DAIFMT_CBM_CFS:
 		/* codec is clock master and frame slave */
@@ -745,6 +749,7 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		/* bit stream is MSB first  with no delay */
 		/* DSP_B mode */
+	  	mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
 		mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
 		mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
 
@@ -754,6 +759,8 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
 		else
 			printk(KERN_ERR "playback tdm slot %d not supported\n",
 				dev->tdm_slots);
+		mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+		mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
 	} else {
 		/* bit stream is MSB first with no delay */
 		/* DSP_B mode */
@@ -1047,6 +1054,22 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
 		pdata->serial_dir = of_serial_dir;
 	}
 
+	ret = of_property_read_u32(np, "asp-chan-q", &pdata->asp_chan_q);
+	if (ret < 0)
+		goto nodata;
+
+	ret = of_property_read_u32(np, "ram-chan-q", &val);
+	if (ret >= 0)
+		pdata->ram_chan_q = val;
+
+	ret = of_property_read_u32(np, "tx-dma-offset",	&pdata->tx_dma_offset);
+	if (ret < 0)
+		goto nodata;
+
+	ret = of_property_read_u32(np, "rx-dma-offset",	&pdata->rx_dma_offset);
+	if (ret < 0)
+		goto nodata;
+
 	ret = of_property_read_u32(np, "tx-num-evt", &val);
 	if (ret >= 0)
 		pdata->txnumevt = val;
@@ -1080,6 +1103,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 	struct resource *mem, *ioarea, *res;
 	struct snd_platform_data *pdata;
 	struct davinci_audio_dev *dev;
+	struct pinctrl *pinctrl;
 	int ret;
 
 	if (!pdev->dev.platform_data && !pdev->dev.of_node) {
@@ -1111,6 +1135,11 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 		return -EBUSY;
 	}
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev,
+				"pins are not configured from the driver\n");
+
 	pm_runtime_enable(&pdev->dev);
 
 	ret = pm_runtime_get_sync(&pdev->dev);
@@ -1140,13 +1169,16 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 	dma_data->ram_chan_q = pdata->ram_chan_q;
 	dma_data->sram_pool = pdata->sram_pool;
 	dma_data->sram_size = pdata->sram_size_playback;
-	dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
+	if (dev->version == MCASP_VERSION_3)
+		dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset);
+	else
+		dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
 							mem->start);
 
 	/* first TX, then RX */
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
 	if (!res) {
-		dev_err(&pdev->dev, "no DMA resource\n");
+		dev_err(&pdev->dev, "Failed to get tx dma resource\n");
 		ret = -ENODEV;
 		goto err_release_clk;
 	}
@@ -1158,12 +1190,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 	dma_data->ram_chan_q = pdata->ram_chan_q;
 	dma_data->sram_pool = pdata->sram_pool;
 	dma_data->sram_size = pdata->sram_size_capture;
-	dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
+	if (dev->version == MCASP_VERSION_3)
+		dma_data->dma_addr = (dma_addr_t) (pdata->rx_dma_offset);
+	else
+		dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
 							mem->start);
 
-	res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
 	if (!res) {
-		dev_err(&pdev->dev, "no DMA resource\n");
+		dev_err(&pdev->dev, "Failed to get rx dma resource\n");
 		ret = -ENODEV;
 		goto err_release_clk;
 	}
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index afab81f..9bdd71b 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -17,6 +17,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/genalloc.h>
+#include <linux/platform_data/edma.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
index b6ef703..fbb710c 100644
--- a/sound/soc/davinci/davinci-pcm.h
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -14,7 +14,7 @@
 
 #include <linux/genalloc.h>
 #include <linux/platform_data/davinci_asp.h>
-#include <mach/edma.h>
+#include <linux/platform_data/edma.h>
 
 struct davinci_pcm_dma_params {
 	int channel;			/* sync dma channel ID */
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c
index 5be65aa..074fc5d 100644
--- a/sound/soc/davinci/davinci-sffsdr.c
+++ b/sound/soc/davinci/davinci-sffsdr.c
@@ -17,6 +17,7 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/platform_data/edma.h>
 #include <linux/gpio.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -28,7 +29,6 @@
 #include <asm/plat-sffsdr/sffsdr-fpga.h>
 #endif
 
-#include <mach/edma.h>
 
 #include "../codecs/pcm3008.h"
 #include "davinci-pcm.h"
@@ -123,8 +123,8 @@ static struct resource sffsdr_snd_resources[] = {
 };
 
 static struct evm_snd_platform_data sffsdr_snd_data = {
-	.tx_dma_ch	= DAVINCI_DMA_MCBSP_TX,
-	.rx_dma_ch	= DAVINCI_DMA_MCBSP_RX,
+	.tx_dma_ch	= 2,	/* MCBSP_TX */
+	.rx_dma_ch	= 3,	/* MCBSP_RX */
 };
 
 static struct platform_device *sffsdr_snd_device;
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index a20e320..0b0a907 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -122,7 +122,7 @@ export Q VERBOSE
 
 EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
 
-INCLUDES = -I. -I/usr/local/include $(CONFIG_INCLUDES)
+INCLUDES = -I. $(CONFIG_INCLUDES)
 
 # Set compile option CFLAGS if not set elsewhere
 CFLAGS ?= -g -Wall
