diff --git a/Documentation/devicetree/bindings/reset/gpio-reset.txt b/Documentation/devicetree/bindings/reset/gpio-reset.txt
index bca5348..2927fae 100644
--- a/Documentation/devicetree/bindings/reset/gpio-reset.txt
+++ b/Documentation/devicetree/bindings/reset/gpio-reset.txt
@@ -18,6 +18,9 @@ Optional properties:
                       deasserted reset line. If this property exists, the
                       reset line should be kept in reset.
 
+- gpio-can-sleep: boolean. If not set, then initial state is false.
+                  Make the gpio-core use the correct gpio_set() function.
+
 example:
 
 sii902x_reset: gpio-reset {
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d4f292a..8ae2a7e 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -330,7 +330,13 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6q-tx6q-1110.dtb \
 	imx6q-udoo.dtb \
 	imx6q-wandboard.dtb \
-	imx6q-wandboard-revb1.dtb
+	imx6q-wandboard-revb1.dtb \
+	imx6dl-cm-fx6.dtb \
+	imx6dl-sbc-fx6.dtb \
+	imx6dl-sbc-fx6m.dtb \
+	imx6q-cm-fx6.dtb \
+	imx6q-sbc-fx6.dtb \
+	imx6q-sbc-fx6m.dtb
 dtb-$(CONFIG_SOC_IMX6SL) += \
 	imx6sl-evk.dtb \
 	imx6sl-evk-btwifi.dtb \
diff --git a/arch/arm/boot/dts/imx6dl-cm-fx6.dts b/arch/arm/boot/dts/imx6dl-cm-fx6.dts
new file mode 100644
index 0000000..d33d14c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-cm-fx6.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2015 CompuLab Ltd.
+ *
+ * Author: Valentin Raevsky <valentin@compulab.co.il>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-cm-fx6.dtsi"
+
+/ {
+	model = "CompuLab CM-FX6";
+	compatible = "compulab,cm-fx6", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sbc-fx6-hdmi.dts b/arch/arm/boot/dts/imx6dl-sbc-fx6-hdmi.dts
new file mode 100644
index 0000000..2d31883
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sbc-fx6-hdmi.dts
@@ -0,0 +1,24 @@
+/*
+* Copyright 2015 CompuLab Ltd.
+*
+* Author: Valentin Raevsky <valentin@compulab.co.il>
+*
+* The code contained herein is licensed under the GNU General Public
+* License. You may obtain a copy of the GNU General Public License
+* Version 2 or later at the following locations:
+*
+* http://www.opensource.org/licenses/gpl-license.html
+* http://www.gnu.org/copyleft/gpl.html
+*/
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-cm-fx6.dtsi"
+#include "imx6qdl-sb-fx6x.dtsi"
+#include "imx6qdl-sb-fx6.dtsi"
+#include "imx6qdl-cm-fx6-hdmi.dtsi"
+
+/ {
+	model = "CompuLab CM-FX6 on SBC-FX6";
+	compatible = "compulab,cm-fx6", "compulab,sbc-fx6", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sbc-fx6-mipi.dts b/arch/arm/boot/dts/imx6dl-sbc-fx6-mipi.dts
new file mode 100644
index 0000000..3617c14
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sbc-fx6-mipi.dts
@@ -0,0 +1,24 @@
+/*
+* Copyright 2015 CompuLab Ltd.
+*
+* Author: Valentin Raevsky <valentin@compulab.co.il>
+*
+* The code contained herein is licensed under the GNU General Public
+* License. You may obtain a copy of the GNU General Public License
+* Version 2 or later at the following locations:
+*
+* http://www.opensource.org/licenses/gpl-license.html
+* http://www.gnu.org/copyleft/gpl.html
+*/
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-cm-fx6.dtsi"
+#include "imx6qdl-sb-fx6x.dtsi"
+#include "imx6qdl-sb-fx6.dtsi"
+#include "imx6qdl-cm-fx6-mipi.dtsi"
+
+/ {
+	model = "CompuLab CM-FX6 on SBC-FX6";
+	compatible = "compulab,cm-fx6", "compulab,sbc-fx6", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sbc-fx6.dts b/arch/arm/boot/dts/imx6dl-sbc-fx6.dts
new file mode 100644
index 0000000..723b654
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sbc-fx6.dts
@@ -0,0 +1,23 @@
+/*
+* Copyright 2015 CompuLab Ltd.
+*
+* Author: Valentin Raevsky <valentin@compulab.co.il>
+*
+* The code contained herein is licensed under the GNU General Public
+* License. You may obtain a copy of the GNU General Public License
+* Version 2 or later at the following locations:
+*
+* http://www.opensource.org/licenses/gpl-license.html
+* http://www.gnu.org/copyleft/gpl.html
+*/
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-cm-fx6.dtsi"
+#include "imx6qdl-sb-fx6x.dtsi"
+#include "imx6qdl-sb-fx6.dtsi"
+
+/ {
+	model = "CompuLab CM-FX6 on SBC-FX6";
+	compatible = "compulab,cm-fx6", "compulab,sbc-fx6", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-sbc-fx6m.dts b/arch/arm/boot/dts/imx6dl-sbc-fx6m.dts
new file mode 100644
index 0000000..f66b177
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-sbc-fx6m.dts
@@ -0,0 +1,23 @@
+/*
+* Copyright 2015 CompuLab Ltd.
+*
+* Author: Valentin Raevsky <valentin@compulab.co.il>
+*
+* The code contained herein is licensed under the GNU General Public
+* License. You may obtain a copy of the GNU General Public License
+* Version 2 or later at the following locations:
+*
+* http://www.opensource.org/licenses/gpl-license.html
+* http://www.gnu.org/copyleft/gpl.html
+*/
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-cm-fx6.dtsi"
+#include "imx6qdl-sb-fx6x.dtsi"
+#include "imx6qdl-sb-fx6m.dtsi"
+
+/ {
+	model = "CompuLab CM-FX6 on SBC-FX6m";	
+	compatible = "compulab,cm-fx6", "compulab,sbc-fx6m", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6q-cm-fx6.dts b/arch/arm/boot/dts/imx6q-cm-fx6.dts
index 99b46f8..14c2d6a 100644
--- a/arch/arm/boot/dts/imx6q-cm-fx6.dts
+++ b/arch/arm/boot/dts/imx6q-cm-fx6.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013 CompuLab Ltd.
+ * Copyright 2014 CompuLab Ltd.
  *
  * Author: Valentin Raevsky <valentin@compulab.co.il>
  *
@@ -13,95 +13,9 @@
 
 /dts-v1/;
 #include "imx6q.dtsi"
+#include "imx6q-cm-fx6.dtsi"
 
 / {
 	model = "CompuLab CM-FX6";
 	compatible = "compulab,cm-fx6", "fsl,imx6q";
-
-	memory {
-		reg = <0x10000000 0x80000000>;
-	};
-
-	leds {
-		compatible = "gpio-leds";
-
-		heartbeat-led {
-			label = "Heartbeat";
-			gpios = <&gpio2 31 0>;
-			linux,default-trigger = "heartbeat";
-		};
-	};
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet>;
-	phy-mode = "rgmii";
-	status = "okay";
-};
-
-&gpmi {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_gpmi_nand>;
-	status = "okay";
-};
-
-&iomuxc {
-	imx6q-cm-fx6 {
-		pinctrl_enet: enetgrp {
-			fsl,pins = <
-				MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
-				MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
-				MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
-				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
-				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
-				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
-				MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
-				MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b0b0
-				MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b0b0
-				MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b0b0
-				MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b0b0
-				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b0b0
-				MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
-				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
-				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
-				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
-			>;
-		};
-
-		pinctrl_gpmi_nand: gpminandgrp {
-			fsl,pins = <
-				MX6QDL_PAD_NANDF_CLE__NAND_CLE		0xb0b1
-				MX6QDL_PAD_NANDF_ALE__NAND_ALE		0xb0b1
-				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0xb0b1
-				MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0xb000
-				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0xb0b1
-				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B	0xb0b1
-				MX6QDL_PAD_SD4_CMD__NAND_RE_B		0xb0b1
-				MX6QDL_PAD_SD4_CLK__NAND_WE_B		0xb0b1
-				MX6QDL_PAD_NANDF_D0__NAND_DATA00	0xb0b1
-				MX6QDL_PAD_NANDF_D1__NAND_DATA01	0xb0b1
-				MX6QDL_PAD_NANDF_D2__NAND_DATA02	0xb0b1
-				MX6QDL_PAD_NANDF_D3__NAND_DATA03	0xb0b1
-				MX6QDL_PAD_NANDF_D4__NAND_DATA04	0xb0b1
-				MX6QDL_PAD_NANDF_D5__NAND_DATA05	0xb0b1
-				MX6QDL_PAD_NANDF_D6__NAND_DATA06	0xb0b1
-				MX6QDL_PAD_NANDF_D7__NAND_DATA07	0xb0b1
-				MX6QDL_PAD_SD4_DAT0__NAND_DQS		0x00b1
-			>;
-		};
-
-		pinctrl_uart4: uart4grp {
-			fsl,pins = <
-				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
-				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
-			>;
-		};
-	};
-};
-
-&uart4 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart4>;
-	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6q-cm-fx6.dtsi b/arch/arm/boot/dts/imx6q-cm-fx6.dtsi
new file mode 100644
index 0000000..0cdba81
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-cm-fx6.dtsi
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2014 CompuLab Ltd.
+ *
+ * Author: Valentin Raevsky <valentin@compulab.co.il>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx6qdl-cm-fx6.dtsi"
+
+/ {
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		reg_sata_ldo_en: sata_ldo_en {
+			compatible = "regulator-fixed";
+			regulator-name = "cm_fx6_sata_ldo_en";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio2 16 0>;
+			startup-delay-us = <100>;
+			enable-active-high;
+		};
+
+		reg_sata_phy_slp: sata_phy_slp {
+			compatible = "regulator-fixed";
+			regulator-name = "cm_fx6_sata_phy_slp";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio3 23 0>;
+			startup-delay-us = <100>;
+			enable-active-high;
+			vin-supply = <&reg_sata_ldo_en>;
+		};
+
+		reg_sata_nrstdly: sata_nrstdly {
+			compatible = "regulator-fixed";
+			regulator-name = "cm_fx6_sata_nrstdly";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio6 6 0>;
+			startup-delay-us = <100>;
+			enable-active-high;
+			vin-supply = <&reg_sata_phy_slp>;
+		};
+
+		reg_sata_pwren: sata_pwren {
+			compatible = "regulator-fixed";
+			regulator-name = "cm_fx6_sata_pwren";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio1 28 0>;
+			startup-delay-us = <100>;
+			enable-active-high;
+			vin-supply = <&reg_sata_nrstdly>;
+		};
+
+		reg_sata_nstandby1: sata_nstandby1 {
+			compatible = "regulator-fixed";
+			regulator-name = "cm_fx6_sata_nstandby1";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio3 20 0>;
+			startup-delay-us = <100>;
+			enable-active-high;
+			vin-supply = <&reg_sata_pwren>;
+		};
+
+		reg_sata_nstandby2: sata_nstandby2 {
+			compatible = "regulator-fixed";
+			regulator-name = "cm_fx6_sata_nstandby2";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio5 2 0>;
+			startup-delay-us = <100>;
+			enable-active-high;
+			regulator-boot-on;
+			vin-supply = <&reg_sata_nstandby1>;
+		};
+
+	};
+
+};
+
+/* sata */
+&sata {
+	target-supply = <&reg_sata_nstandby2>;
+	status = "okay";
+	fsl,transmit-level-mV = <1104>;
+	fsl,transmit-boost-mdB = <370>;
+	fsl,transmit-atten-16ths = <9>;
+	fsl,receive-eq-mdB = <3000>;
+};
diff --git a/arch/arm/boot/dts/imx6q-sbc-fx6-hdmi.dts b/arch/arm/boot/dts/imx6q-sbc-fx6-hdmi.dts
new file mode 100644
index 0000000..309fd1c
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sbc-fx6-hdmi.dts
@@ -0,0 +1,24 @@
+/*
+* Copyright 2014 CompuLab Ltd.
+*
+* Author: Valentin Raevsky <valentin@compulab.co.il>
+*
+* The code contained herein is licensed under the GNU General Public
+* License. You may obtain a copy of the GNU General Public License
+* Version 2 or later at the following locations:
+*
+* http://www.opensource.org/licenses/gpl-license.html
+* http://www.gnu.org/copyleft/gpl.html
+*/
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6q-cm-fx6.dtsi"
+#include "imx6qdl-sb-fx6x.dtsi"
+#include "imx6qdl-sb-fx6.dtsi"
+#include "imx6qdl-cm-fx6-hdmi.dtsi"
+
+/ {
+	model = "CompuLab CM-FX6 on SBC-FX6";
+	compatible = "compulab,cm-fx6", "compulab,sbc-fx6", "fsl,imx6q";
+};
diff --git a/arch/arm/boot/dts/imx6q-sbc-fx6-mipi.dts b/arch/arm/boot/dts/imx6q-sbc-fx6-mipi.dts
new file mode 100644
index 0000000..fb13ef3
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sbc-fx6-mipi.dts
@@ -0,0 +1,24 @@
+/*
+* Copyright 2014 CompuLab Ltd.
+*
+* Author: Valentin Raevsky <valentin@compulab.co.il>
+*
+* The code contained herein is licensed under the GNU General Public
+* License. You may obtain a copy of the GNU General Public License
+* Version 2 or later at the following locations:
+*
+* http://www.opensource.org/licenses/gpl-license.html
+* http://www.gnu.org/copyleft/gpl.html
+*/
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6q-cm-fx6.dtsi"
+#include "imx6qdl-sb-fx6x.dtsi"
+#include "imx6qdl-sb-fx6.dtsi"
+#include "imx6qdl-cm-fx6-mipi.dtsi"
+
+/ {
+	model = "CompuLab CM-FX6 on SBC-FX6";
+	compatible = "compulab,cm-fx6", "compulab,sbc-fx6", "fsl,imx6q";
+};
diff --git a/arch/arm/boot/dts/imx6q-sbc-fx6.dts b/arch/arm/boot/dts/imx6q-sbc-fx6.dts
new file mode 100644
index 0000000..1234fb3
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sbc-fx6.dts
@@ -0,0 +1,23 @@
+/*
+* Copyright 2014 CompuLab Ltd.
+*
+* Author: Valentin Raevsky <valentin@compulab.co.il>
+*
+* The code contained herein is licensed under the GNU General Public
+* License. You may obtain a copy of the GNU General Public License
+* Version 2 or later at the following locations:
+*
+* http://www.opensource.org/licenses/gpl-license.html
+* http://www.gnu.org/copyleft/gpl.html
+*/
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6q-cm-fx6.dtsi"
+#include "imx6qdl-sb-fx6x.dtsi"
+#include "imx6qdl-sb-fx6.dtsi"
+
+/ {
+	model = "CompuLab CM-FX6 on SBC-FX6";
+	compatible = "compulab,cm-fx6", "compulab,sbc-fx6", "fsl,imx6q";
+};
diff --git a/arch/arm/boot/dts/imx6q-sbc-fx6m.dts b/arch/arm/boot/dts/imx6q-sbc-fx6m.dts
new file mode 100644
index 0000000..7be1a4f
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-sbc-fx6m.dts
@@ -0,0 +1,24 @@
+/*
+* Copyright 2014 CompuLab Ltd.
+*
+* Author: Valentin Raevsky <valentin@compulab.co.il>
+*
+* The code contained herein is licensed under the GNU General Public
+* License. You may obtain a copy of the GNU General Public License
+* Version 2 or later at the following locations:
+*
+* http://www.opensource.org/licenses/gpl-license.html
+* http://www.gnu.org/copyleft/gpl.html
+*/
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6q-cm-fx6.dtsi"
+#include "imx6qdl-sb-fx6x.dtsi"
+#include "imx6qdl-sb-fx6m.dtsi"
+
+/ {
+	model = "CompuLab CM-FX6 on SBC-FX6m";	
+	compatible = "compulab,cm-fx6", "compulab,sbc-fx6m", "fsl,imx6q";
+};
+
diff --git a/arch/arm/boot/dts/imx6qdl-cm-fx6-hdmi.dtsi b/arch/arm/boot/dts/imx6qdl-cm-fx6-hdmi.dtsi
new file mode 100644
index 0000000..47f8ab6
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-cm-fx6-hdmi.dtsi
@@ -0,0 +1,9 @@
+&mxcfb1 {
+	mode_str ="1920x1080M@60";
+	disp_dev = "hdmi";
+};
+
+&mxcfb2 {
+	mode_str ="KD050C-WVGA";
+	disp_dev = "lcd";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-cm-fx6-mipi.dtsi b/arch/arm/boot/dts/imx6qdl-cm-fx6-mipi.dtsi
new file mode 100644
index 0000000..9f9a9c9
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-cm-fx6-mipi.dtsi
@@ -0,0 +1,35 @@
+&ipu1di0_disp {
+	status = "disabled";
+};
+
+&mipi_dsi {
+	dev_id = <0>;
+	disp_id = <0>;
+	lcd_panel = "TRULY-WVGA";
+	depends = &pca9555;
+	disp-power-on-supply = <&reg_mipi_dsi_pwr_on_mode>;
+	resets = <&mipi_dsi_reset>;
+	status = "okay";
+};
+
+&mxcfb1 {
+	mode_str ="TRULY-WVGA";
+	disp_dev = "mipi_dsi";
+	depends = &mipi_dsi;
+	status = "okay";
+};
+
+&mxcfb2 {
+	depends = &mipi_dsi;
+	status = "okay";
+};
+
+&mxcfb3 {
+	depends = &mipi_dsi;
+	status = "okay";
+};
+
+&mxcfb4 {
+	depends = &mipi_dsi;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-cm-fx6.dtsi b/arch/arm/boot/dts/imx6qdl-cm-fx6.dtsi
new file mode 100644
index 0000000..11789f2
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-cm-fx6.dtsi
@@ -0,0 +1,772 @@
+/*
+ * Copyright 2014 CompuLab Ltd.
+ *
+ * Author: Valentin Raevsky <valentin@compulab.co.il>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <dt-bindings/sound/fsl-imx-audmux.h>
+
+#define MX6QDL_GPR1	0x04 0x04 0x000 0x0 0x0
+
+/ {
+	memory {
+		reg = <0x10000000 0x20000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		heartbeat-led {
+			label = "Heartbeat";
+			gpios = <&gpio2 31 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* regulator for usb otg */
+		reg_usb_otg_vbus: usb_otg_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 22 0>;
+			enable-active-high;
+		};
+
+		/* regulator for usb hub1 */
+		reg_usb_h1_vbus: usb_h1_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb_h1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio7 8 0>;
+			enable-active-high;
+		};
+
+		/* regulator1 for wifi/bt */
+		awnh387_npoweron: regulator-awnh387-npoweron {
+			compatible = "regulator-fixed";
+			regulator-name = "regulator-awnh387-npoweron";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio7 12 0>;
+			enable-active-high;
+		};
+
+		/* regulator2 for wifi/bt */
+		awnh387_wifi_nreset: regulator-awnh387-wifi-nreset {
+			compatible = "regulator-fixed";
+			regulator-name = "regulator-awnh387-wifi-nreset";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio6 16 0>;
+			startup-delay-us = <10000>;
+		};
+
+		tsc2046reg: tsc2046-reg {
+			compatible = "regulator-fixed";
+			regulator-name = "tsc2046-reg";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+		};
+
+	};
+
+	pu_dummy: pudummy_reg {
+		compatible = "fsl,imx6-dummy-pureg"; /* only used in ldo-bypass */
+	};
+
+	aliases {
+		mxcfb0 = &mxcfb1;
+		mxcfb1 = &mxcfb2;
+		mxcfb2 = &mxcfb3;
+		mxcfb3 = &mxcfb4;
+	};
+
+	simple_sound: sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "cm-fx6";
+		simple-audio-card,widgets =
+			"Headphone", "Headphone Jack",
+			"Line", "Line Out",
+			"Microphone", "Mic Jack",
+			"Line", "Line In";
+		simple-audio-card,routing =
+			"Headphone Jack", "RHPOUT",
+			"Headphone Jack", "LHPOUT",
+			"MICIN", "Mic Bias",
+			"Mic Bias", "Mic Jack";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&sound_master>;
+		simple-audio-card,frame-master = <&sound_master>;
+		simple-audio-card,bitclock-inversion;
+
+		sound_master: simple-audio-card,cpu {
+			sound-dai = <&ssi2>;
+			system-clock-frequency = <0>;
+			system-clock-direction = "out";
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&wm8731>;
+			system-clock-direction = "in";
+		};
+
+	};
+
+	sound-hdmi {
+		compatible = "fsl,imx-audio-hdmi";
+		model = "imx-audio-hdmi";
+		hdmi-controller = <&hdmi_audio>;
+	};
+
+	sound-spdif {
+		compatible = "fsl,imx-audio-spdif";
+		model = "imx-spdif";
+		spdif-controller = <&spdif>;
+		spdif-out;
+		spdif-in;
+	};
+
+	mxcfb1: fb@0 {
+		compatible = "fsl,mxc_sdc_fb";
+		disp_dev = "lcd";
+		interface_pix_fmt = "RGB24";
+		mode_str ="1920x1080M@60";
+		default_bpp = <32>;
+		int_clk = <0>;
+		late_init = <0>;
+		status = "disabled";
+	};
+
+	mxcfb2: fb@1 {
+		compatible = "fsl,mxc_sdc_fb";
+		disp_dev = "hdmi";
+		interface_pix_fmt = "RGB24";
+		mode_str ="1920x1080M@60";
+		default_bpp = <32>;
+		int_clk = <0>;
+		late_init = <0>;
+		status = "disabled";
+	};
+
+	mxcfb3: fb@2 {
+		compatible = "fsl,mxc_sdc_fb";
+		disp_dev = "ldb";
+		interface_pix_fmt = "RGB666";
+		mode_str ="1366x768M-18@60";
+		default_bpp = <16>;
+		int_clk = <0>;
+		late_init = <0>;
+		status = "disabled";
+	};
+
+	mxcfb4: fb@3 {
+		compatible = "fsl,mxc_sdc_fb";
+		disp_dev = "ldb";
+		interface_pix_fmt = "RGB666";
+		mode_str ="1280x800M-18@60";
+		default_bpp = <16>;
+		int_clk = <0>;
+		late_init = <0>;
+		status = "disabled";
+	};
+
+	ipu1di0_disp: ipu1@0 {
+		compatible = "fsl,lcd";
+		ipu_id = <0>;
+		disp_id = <0>;
+		default_ifmt = "RGB24";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_ipu1_di0>;
+		status = "okay";
+	};
+
+	v4l2_cap {
+		compatible = "fsl,imx6q-v4l2-capture";
+		ipu_id = <0>;
+		csi_id = <0>;
+		mclk_source = <0>;
+		status = "okay";
+	};
+
+	v4l2_out {
+		compatible = "fsl,mxc_v4l2_output";
+		status = "okay";
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	hog {
+		pinctrl_hog: hoggrp {
+			fsl,pins = <
+				MX6QDL_GPR1 0x48400005
+				/* SATA PWR */
+				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000
+				MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x80000000
+				MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x80000000
+				MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000
+				/* SATA CTRL */
+				MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000
+				MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000
+				MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x80000000
+				MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
+				/* POWER_BUTTON */
+				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
+				/* PHY_RST */
+				MX6QDL_PAD_SD4_DAT0__GPIO2_IO08	0x80000000
+				/* mipi camera rst pwn */
+				MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x80000000
+				MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000
+			>;
+		};
+	};
+
+	imx6q-cm-fx6 {
+		/* pins for eth0 */
+		pinctrl_enet: enetgrp {
+			fsl,pins = <
+				MX6QDL_PAD_RGMII_RXC__RGMII_RXC      0x1b0b0
+				MX6QDL_PAD_RGMII_RD0__RGMII_RD0      0x1b0b0
+				MX6QDL_PAD_RGMII_RD1__RGMII_RD1      0x1b0b0
+				MX6QDL_PAD_RGMII_RD2__RGMII_RD2      0x1b0b0
+				MX6QDL_PAD_RGMII_RD3__RGMII_RD3      0x1b0b0
+				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL   0x1b0b0
+				MX6QDL_PAD_RGMII_TXC__RGMII_TXC      0x1b0b0
+				MX6QDL_PAD_RGMII_TD0__RGMII_TD0      0x1b0b0
+				MX6QDL_PAD_RGMII_TD1__RGMII_TD1      0x1b0b0
+				MX6QDL_PAD_RGMII_TD2__RGMII_TD2      0x1b0b0
+				MX6QDL_PAD_RGMII_TD3__RGMII_TD3      0x1b0b0
+				MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL   0x1b0b0
+				MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK   0x1b0b0
+				MX6QDL_PAD_ENET_MDIO__ENET_MDIO      0x1b0b0
+				MX6QDL_PAD_ENET_MDC__ENET_MDC      0x1b0b0
+			>;
+		};
+
+		pinctrl_ipu1_di0: ipu1grp-di0 {
+			fsl,pins = <
+				MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x38
+				MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x38
+				MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x38
+				MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x38
+				MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00   0x38
+				MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x38
+				MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x38
+				MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x38
+				MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x38
+				MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x38
+				MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x38
+				MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x38
+				MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x38
+				MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x38
+				MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x38
+				MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x38
+				MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x38
+				MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x38
+				MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x38
+				MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x38
+				MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x38
+				MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x38
+				MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x38
+				MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x38
+				MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x38
+				MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x38
+				MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x38
+				MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x38
+			>;
+		};
+
+		/* pins for spi */
+		pinctrl_ecspi1: ecspi1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK      0x100b1
+				MX6QDL_PAD_EIM_D17__ECSPI1_MISO      0x100b1
+				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI      0x100b1
+				MX6QDL_PAD_EIM_EB2__GPIO2_IO30      0x100b1
+				MX6QDL_PAD_EIM_D19__GPIO3_IO19      0x100b1
+			>;
+		};
+
+		/* pins for nand */
+		pinctrl_gpmi_nand: gpminandgrp {
+			fsl,pins = <
+				MX6QDL_PAD_NANDF_CLE__NAND_CLE      0xb0b1
+				MX6QDL_PAD_NANDF_ALE__NAND_ALE      0xb0b1
+				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B   0xb0b1
+				MX6QDL_PAD_NANDF_RB0__NAND_READY_B   0xb000
+				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B   0xb0b1
+				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B   0xb0b1
+				MX6QDL_PAD_SD4_CMD__NAND_RE_B      0xb0b1
+				MX6QDL_PAD_SD4_CLK__NAND_WE_B      0xb0b1
+				MX6QDL_PAD_NANDF_D0__NAND_DATA00   0xb0b1
+				MX6QDL_PAD_NANDF_D1__NAND_DATA01   0xb0b1
+				MX6QDL_PAD_NANDF_D2__NAND_DATA02   0xb0b1
+				MX6QDL_PAD_NANDF_D3__NAND_DATA03   0xb0b1
+				MX6QDL_PAD_NANDF_D4__NAND_DATA04   0xb0b1
+				MX6QDL_PAD_NANDF_D5__NAND_DATA05   0xb0b1
+				MX6QDL_PAD_NANDF_D6__NAND_DATA06   0xb0b1
+				MX6QDL_PAD_NANDF_D7__NAND_DATA07   0xb0b1
+			>;
+		};
+
+		pinctrl_hdmi_hdcp: hdmihdcpgrp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL 0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
+			>;
+		};
+
+		/* pins for i2c2 */
+		pinctrl_i2c2: i2c2grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+				MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+			>;
+		};
+
+		/* pins for i2c3 */
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+			>;
+		};
+
+		/* pins for ttymxc0 */
+		pinctrl_uart1: uart1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA  0x1b0b1
+				MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA  0x1b0b1
+			>;
+		};
+
+		/* pins for ttymxc1 */
+		pinctrl_uart2: uar2grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_7__UART2_TX_DATA  0x1b0b1
+				MX6QDL_PAD_GPIO_8__UART2_RX_DATA  0x1b0b1
+				MX6QDL_PAD_SD4_DAT5__UART2_RTS_B  0x1b0b1
+				MX6QDL_PAD_SD4_DAT6__UART2_CTS_B  0x1b0b1
+			>;
+		};
+
+		/* pins for ttymxc2 */
+		pinctrl_uart3: uar3grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+				MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+			>;
+		};
+
+		/* pins for ttymxc3 console */
+		pinctrl_uart4: uart4grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL0__UART4_TX_DATA   0x1b0b1
+				MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA   0x1b0b1
+			>;
+		};
+
+		/* pins for ttymxc4 */
+		pinctrl_uart5: uart5grp {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1
+				MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1
+			>;
+		};
+
+		/* pins for usb hub1 */
+		pinctrl_usbh1: usbh1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x80000000
+			>;
+		};
+
+		/* pins for usb otg */
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
+				MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
+			>;
+		};
+
+		/* pins for wifi/bt */
+		pinctrl_usdhc1: usdhc1grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17071
+				MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10071
+				MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17071
+				MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17071
+				MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17071
+				MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17071
+			>;
+		};
+
+		/* pins for wifi/bt */
+		pinctrl_mrvl1: mrvl1grp {
+			fsl,pins = <
+				/* WIFI_PWR_RST */
+				MX6QDL_PAD_GPIO_17__GPIO7_IO12	0x80000000
+				MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x80000000
+			>;
+		};
+
+		/* pins for tsc2046 pendown */
+		pinctrl_tsc2046: tsc2046grp {
+			fsl,pins = <
+				 /* tsc2046 PENDOWN */
+				MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x80000000
+			>;
+		};
+
+		/* pins for pcie */
+		pinctrl_pcie: pciegrp {
+			fsl,pins = <
+				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000
+			>;
+		};
+
+		/* pins for spdif */
+		pinctrl_spdif: spdifgrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_16__SPDIF_IN  0x1b0b0
+				MX6QDL_PAD_GPIO_19__SPDIF_OUT 0x1b0b0
+			>;
+		};
+
+		/* pins for audmux */
+		pinctrl_audmux: audmuxgrp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_CMD__AUD4_RXC   0x17059
+				MX6QDL_PAD_SD2_DAT0__AUD4_RXD  0x17059
+				MX6QDL_PAD_SD2_DAT3__AUD4_TXC  0x17059
+				MX6QDL_PAD_SD2_DAT2__AUD4_TXD  0x17059
+				MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x17059
+				/* master mode pin */
+				MX6QDL_PAD_GPIO_5__CCM_CLKO1	0x17059
+			>;
+		};
+
+		pinctrl_flexcan1_1: flexcan1grp-1 {
+			fsl,pins = <
+				MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000
+				MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x80000000
+			>;
+                };
+
+		pinctrl_pwm3_1: pwm3grp-1 {
+			fsl,pins = <
+				MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
+			>;
+		};
+
+                pinctrl_ipu1_3: ipu1grp-3 { /* parallel port 16-bit */
+                        fsl,pins = <
+                                MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04   0x80000000
+                                MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05   0x80000000
+                                MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06   0x80000000
+                                MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07   0x80000000
+                                MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08   0x80000000
+                                MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09   0x80000000
+                                MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10  0x80000000
+                                MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11  0x80000000
+                                MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12  0x80000000
+                                MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13  0x80000000
+                                MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14  0x80000000
+                                MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15  0x80000000
+                                MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16  0x80000000
+                                MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17  0x80000000
+                                MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18  0x80000000
+                                MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19  0x80000000
+                                MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x80000000
+                                MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC    0x80000000
+                                MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC   0x80000000
+                        >;
+                };
+	};
+};
+
+&cpu0 {
+	operating-points = <
+		/* kHz    uV */
+		996000  1250000
+		852000  1250000
+		792000  1150000
+		396000  975000
+	>;
+	fsl,soc-operating-points = <
+		/* ARM kHz  SOC-PU uV */
+		996000        1250000
+		852000        1250000
+		792000        1175000
+		396000        1175000
+	>;
+};
+
+&gpc {
+	/* use ldo-enable, u-boot will check it and configure */
+	fsl,ldo-bypass = <1>;
+};
+
+/* spi */
+&ecspi1 {
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	status = "okay";
+
+	flash: m25p80@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,m25px16", "st,m25p";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+
+		partition@0 {
+			label = "uboot";
+			reg = <0x0 0xc0000>;
+		};
+
+		partition@c0000 {
+			label = "uboot environment";
+			reg = <0xc0000 0x40000>;
+		};
+
+		partition@100000 {
+			label = "reserved";
+			reg = <0x100000 0x100000>;
+		};
+	};
+
+	/* touch controller */
+	touch:	tsc2046@1 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_tsc2046>;
+
+		compatible = "ti,tsc2046";
+		vcc-supply = <&tsc2046reg>;
+
+		reg = <1>;	/* CS1 */
+		spi-max-frequency = <1500000>;
+
+		interrupt-parent = <&gpio2>;
+		interrupts = <15 0>;
+		pendown-gpio = <&gpio2 15 0>;
+
+		ti,x-min = /bits/ 16 <0x0>;
+		ti,x-max = /bits/ 16 <0x0fff>;
+		ti,y-min = /bits/ 16 <0x0>;
+		ti,y-max = /bits/ 16 <0x0fff>;
+
+		ti,x-plate-ohms = /bits/ 16 <180>;
+		ti,pressure-max = /bits/ 16 <255>;
+
+		ti,debounce-max = /bits/ 16 <30>;
+		ti,debounce-tol = /bits/ 16 <10>;
+		ti,debounce-rep = /bits/ 16 <1>;
+
+		linux,wakeup;
+	};
+};
+
+/* eth0 */
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio2 8 0>;
+	status = "okay";
+};
+
+/* nand */
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	status = "okay";
+	depends = &ecspi1;
+
+	partition@0 {
+		label = "linux";
+		reg = <0x0 0x800000>;
+	};
+
+	partition@800000 {
+		label = "rootfs";
+		reg = < 0x800000 0x0>;
+	};
+};
+
+/* i2c3 */
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	eeprom@50 {
+		compatible = "at24,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	wm8731: wm8731@1a {
+		#sound-dai-cells = <0>;
+		compatible = "wlf,wm8731";
+		reg = <0x1a>;
+		status = "okay";
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio1 26 0>;
+	status = "disabled";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	dma-names = "","tx";
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+/* console */
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+/* usb otg */
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	dr_mode = "otg";
+	status = "okay";
+};
+
+/* usb hub1 */
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbh1>;
+	status = "okay";
+};
+
+/* wifi/bt */
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>, <&pinctrl_mrvl1>;
+	non-removable;
+	vmmc-supply = <&awnh387_npoweron>;
+	vmmc_aux-supply = <&awnh387_wifi_nreset>;
+	status = "okay";
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <786432000>;
+};
+
+&ssi2 {
+	#sound-dai-cells = <0>;
+	fsl,mode = "i2s-master";
+	status = "okay";
+
+	assigned-clocks = <&clks IMX6QDL_CLK_SSI2_SEL>,
+			<&clks IMX6QDL_CLK_SSI2>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <0>;
+};
+
+&hdmi_core {
+	ipu_id = <0>;
+	disp_id = <1>;
+	status = "okay";
+};
+
+&hdmi_video {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hdmi_hdcp>;
+        fsl,phy_reg_vlev = <0x0294>;
+        fsl,phy_reg_cksymtx = <0x800d>;
+	fsl,hdcp;
+	status = "okay";
+};
+
+&hdmi_audio {
+	depends = &simple_sound;
+	status = "okay";
+};
+
+&spdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spdif>;
+	depends = &hdmi_audio;
+	status = "okay";
+};
+
+#define SRC_PORT (1)
+#define EXT_PORT (3)
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+
+	ssi2 {
+		fsl,audmux-port = <SRC_PORT>;
+		fsl,port-config = <
+			(IMX_AUDMUX_V2_PTCR_RCLKDIR |
+			IMX_AUDMUX_V2_PTCR_RCSEL(EXT_PORT | 0x8) |
+			IMX_AUDMUX_V2_PTCR_TCLKDIR |
+			IMX_AUDMUX_V2_PTCR_TCSEL(EXT_PORT))
+			IMX_AUDMUX_V2_PDCR_RXDSEL(EXT_PORT)
+		>;
+	};
+
+	pins5 {
+		fsl,audmux-port = <EXT_PORT>;
+		fsl,port-config = <
+			(IMX_AUDMUX_V2_PTCR_TFSDIR |
+			IMX_AUDMUX_V2_PTCR_TFSEL(SRC_PORT) |
+			IMX_AUDMUX_V2_PTCR_RCLKDIR |
+			IMX_AUDMUX_V2_PTCR_RCSEL(SRC_PORT | 0x8) |
+			IMX_AUDMUX_V2_PTCR_TCLKDIR |
+			IMX_AUDMUX_V2_PTCR_TCSEL(SRC_PORT))
+			IMX_AUDMUX_V2_PDCR_RXDSEL(SRC_PORT)
+		>;
+	};
+};
diff --git a/arch/arm/boot/dts/imx6qdl-sb-fx6.dtsi b/arch/arm/boot/dts/imx6qdl-sb-fx6.dtsi
new file mode 100644
index 0000000..e98e819
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-sb-fx6.dtsi
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2014 CompuLab Ltd.
+ *
+ * Author: Valentin Raevsky <valentin@compulab.co.il>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm3 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+	};
+
+	i2cmux {
+		compatible = "i2c-mux-gpio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		mux-gpios = <&gpio1 2 0>;
+		i2c-parent = <&i2c1>;
+
+		i2c@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			pca9555:pca9555@26 {
+			      compatible = "nxp,pca9555";
+			      gpio-controller;
+			      #gpio-cells = <2>;
+			      reg = <0x26>;
+			};
+
+			hx8526@4a {
+			      compatible = "himax,himax_ts";
+			      reg = <0x4a>;
+			      gpio_intr = <&gpio1 4 0>;
+			};
+
+			eeprom@50 {
+				compatible = "at24,24c02";
+				reg = <0x50>;
+				pagesize = <16>;
+			};
+
+			ov564x_mipi: ov564x_mipi@3c {
+				compatible = "ovti,ov564x_mipi";
+				reg = <0x3c>;
+				clocks = <&clks IMX6QDL_CLK_CKO>;
+				clock-names = "csi_mclk";
+
+				DOVDD-supply = <&vgen4_reg>;
+				AVDD-supply = <&vgen3_reg>;
+				DVDD-supply = <&vgen2_reg>;
+
+				pwn-gpios = <&gpio1 25 1>;
+				rst-gpios = <&gpio4 20 0>;
+
+				csi_id = <0>;
+				mclk = <24000000>;
+				mclk_source = <0>;
+			};
+
+			adv5150: adv5150@5c {
+				compatible = "ti,tvp5150";
+				reg = <0x5c>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_ipu1_3>;
+				clocks = <&clks 201>;
+				clock-names = "csi_mclk";
+				csi_id = <0>;
+				mclk = <27000000>;
+				mclk_source = <0>;
+			};
+		};
+
+		i2c@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			dvi_edid: edid@50 {
+				compatible = "fsl,imx6-dvi-i2c";
+				reg = <0x50>;
+				status = "disabled";
+			};
+		};
+
+	};
+
+	reg_mipi_dsi_pwr_on_mode: mipi_dsi_pwr_on_mode {
+		compatible = "regulator-fixed";
+		regulator-name = "mipi_dsi_pwr_on_mode";
+		gpio = <&pca9555 12 0>;
+		enable-active-high;
+	};
+
+	mipi_dsi_reset: mipi-dsi-reset {
+		compatible = "gpio-reset";
+		reset-gpios = <&pca9555 11 GPIO_ACTIVE_LOW>;
+		reset-delay-us = <100>;
+		gpio-can-sleep;
+		#reset-cells = <0>;
+	};
+
+	vgen2_reg: vgen2 {
+		regulator-min-microvolt = <800000>;
+		regulator-max-microvolt = <1550000>;
+	};
+
+	vgen3_reg: vgen3 {
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vgen4_reg: vgen4 {
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	pcie_power_on_gpio: regulator-pcie-power-on-gpio {
+		compatible = "regulator-fixed";
+		regulator-name = "regulator-pcie-power-on-gpio";
+		gpio = <&pca9555 4 GPIO_ACTIVE_LOW>;
+		enable-active-low;
+	};
+};
+
+&pcie {
+	vdd-supply = <&pcie_power_on_gpio>;
+	status = "okay";
+};
+
+&i2c1 {
+	status = "okay";
+};
+
+&usdhc3 {
+	wp-gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
+	cd-gpios = <&gpio7 1 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3_1>;
+	status = "okay";
+};
+
+&ldb {
+	status = "okay";
+
+	lvds0: lvds-channel@0 {
+		crtc = "ipu2-di0";
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		primary;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+
+	lvds1: lvds-channel@1 {
+		crtc = "ipu2-di1";
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing1>;
+			timing1: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
+&mxcfb1 {
+	mode_str ="KD050C-WVGA";
+	status = "okay";
+};
+
+&mxcfb2 {
+	status = "okay";
+};
+
+&mxcfb3 {
+	status = "okay";
+};
+
+&mxcfb4 {
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1_1>;
+	status = "okay";
+};
+
+&mipi_csi {
+	status = "okay";
+	ipu_id = <0>;
+	csi_id = <0>;
+	v_channel = <0>;
+	lanes = <2>;
+};
diff --git a/arch/arm/boot/dts/imx6qdl-sb-fx6m.dtsi b/arch/arm/boot/dts/imx6qdl-sb-fx6m.dtsi
new file mode 100644
index 0000000..2947e25
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-sb-fx6m.dtsi
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2014 CompuLab Ltd.
+ *
+ * Author: Valentin Raevsky <valentin@compulab.co.il>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	iomux_uart2: pinmux@20E0924 {
+		compatible = "pinctrl-single";
+		reg = <0x20E0000 0x924>;	/* Single register */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0x4>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		power {
+			label = "Power Button";
+			gpios = <&gpio1 29 1>;
+			linux,code = <116>; /* KEY_POWER */
+			gpio-key,wakeup;
+		};
+	};
+
+	i2cmux {
+		compatible = "i2c-mux-gpio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		mux-gpios = <&gpio1 2 0>;
+		i2c-parent = <&i2c1>;
+
+		i2c@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom@50 {
+				compatible = "at24,24c02";
+				reg = <0x50>;
+				pagesize = <16>;
+			};
+
+			rtc@56 {
+				compatible = "emmicro,em3027";
+				reg = <0x56>;
+			};
+		};
+
+		i2c@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			dvi_edid: edid@50 {
+				compatible = "fsl,imx6-dvi-i2c";
+				reg = <0x50>;
+				status = "disabled";
+			};
+		};
+	};
+
+	pcie_power_on_gpio: regulator-pcie-power-on-gpio {
+		compatible = "regulator-fixed";
+		regulator-name = "regulator-pcie-power-on-gpio";
+		gpio = <&gpio2 24 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+};
+
+&iomuxc {
+	imx6q-sbc-fx6m {
+		/* pins for pcie */
+		pinctrl_fx6m_pcie: pciefx6mgrp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x80000000
+			>;
+		};
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>, <&pinctrl_fx6m_pcie>;
+	vdd-supply = <&pcie_power_on_gpio>;
+	status = "okay";
+};
+
+&i2c1 {
+	status = "okay";
+};
+
+&usdhc3 {
+	non-removable;
+	status = "okay";
+};
+
+/* rear serial console */
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&hdmi_core {
+	ipu_id = <1>;
+	disp_id = <0>;
+	status = "okay";
+};
+
+&ipu1di0_disp {
+	compatible = "fsl,dvi";
+	hp_gpio = <4>;
+	ipu_id = <0>;
+	disp_id = <0>;
+	status = "okay";
+};
+
+&dvi_edid {
+	status = "okay";
+};
+
+&mxcfb1 {
+	disp_dev = "hdmi";
+	status = "okay";
+};
+
+&mxcfb2 {
+	disp_dev = "dvi";
+	depends = &ipu1di0_disp;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-sb-fx6x.dtsi b/arch/arm/boot/dts/imx6qdl-sb-fx6x.dtsi
new file mode 100644
index 0000000..77a77fe
--- /dev/null
+++ b/arch/arm/boot/dts/imx6qdl-sb-fx6x.dtsi
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2014 CompuLab Ltd.
+ *
+ * Author: Valentin Raevsky <valentin@compulab.co.il>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/ {
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* regulator for mmc */
+		reg_3p3v: 3p3v {
+			compatible = "regulator-fixed";
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+
+	eth@pcie {
+		compatible = "intel,i211";
+		local-mac-address = [FF FF FF FF FF FF];
+		status = "okay";
+	};
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>, <&pinctrl_dvi0>;
+
+	imx6q-sb-fx6x {
+		/* pins for i2c1 */
+		pinctrl_i2c1: i2c1grp {
+			fsl,pins = <
+				MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+			>;
+		};
+
+		/* pins for mmc */
+		pinctrl_usdhc3: usdhc3grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD    0x17059
+				MX6QDL_PAD_SD3_CLK__SD3_CLK    0x10059
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+				MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x80000000
+				MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x80000000
+			>;
+		};
+
+		pinctrl_usdhc3_100mhz: usdhc3grp-100mhz { /* 100Mhz */
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170B9
+				MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100B9
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170B9
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170B9
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170B9
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170B9
+			>;
+		};
+
+		pinctrl_usdhc3_200mhz: usdhc3grp-200mhz { /* 200Mhz */
+			fsl,pins = <
+				MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170F9
+				MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100F9
+				MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170F9
+				MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170F9
+				MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170F9
+				MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170F9
+			>;
+		};
+
+		/* pins for dvi/ts */
+		pinctrl_dvi0: dvi0grp {
+			fsl,pins = <
+				/* DVI_DDC_SEL */
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000
+				/* SB-FX6 Himax TS PENDOWN or SB-FX6m DVI HPD */
+				MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x80000000
+			>;
+		};
+	};
+};
+
+/* i2c1 */
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "disabled";
+};
+
+/* mmc */
+&usdhc3 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+	no-1-8-v;
+	keep-power-in-suspend;
+	vmmc-supply = <&reg_3p3v>;
+	status = "disabled";
+};
diff --git a/arch/arm/configs/cm_fx6_defconfig b/arch/arm/configs/cm_fx6_defconfig
new file mode 100644
index 0000000..cb8fcd1
--- /dev/null
+++ b/arch/arm/configs/cm_fx6_defconfig
@@ -0,0 +1,436 @@
+CONFIG_LOCALVERSION="-cm-fx6-8.0"
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_CHECKPOINT_RESTORE=y
+CONFIG_NAMESPACES=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_MXC=y
+CONFIG_SOC_IMX53=y
+CONFIG_SOC_IMX6Q=y
+CONFIG_SOC_IMX6SL=y
+CONFIG_SOC_VF610=y
+CONFIG_MACH_CM_FX6=y
+# CONFIG_SWP_EMULATE is not set
+CONFIG_PCI=y
+CONFIG_PCI_IMX6=y
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_CMA=y
+CONFIG_SECCOMP=y
+CONFIG_CMDLINE="console=ttymxc3,115200 root=/dev/mmcblk0p1 rootwait"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=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_ARM_IMX6Q_CPUFREQ=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_NAT_IPV4=m
+CONFIG_IP_NF_IPTABLES=y
+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=y
+CONFIG_IP_NF_TARGET_REJECT=y
+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_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_CAN=y
+CONFIG_CAN_FLEXCAN=y
+CONFIG_BT=m
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_CFG80211=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_IMX_WEIM=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_SST25L=y
+CONFIG_MTD_BLOCK2MTD=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_GPMI_NAND=y
+CONFIG_MTD_NAND_MXC=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=m
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_IMX=y
+CONFIG_PATA_IMX=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_CS89x0=y
+CONFIG_CS89x0_PLATFORM=y
+# CONFIG_NET_VENDOR_FARADAY is not set
+CONFIG_IGB=m
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+# CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_ATH_CARDS=y
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_IMX=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_EGALAX=y
+CONFIG_TOUCHSCREEN_ELAN=y
+CONFIG_TOUCHSCREEN_MAX11801=y
+CONFIG_TOUCHSCREEN_MC13783=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=y
+CONFIG_INPUT_ISL29023=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_FSL_LPUART=y
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
+CONFIG_FSL_OTP=y
+CONFIG_HW_RANDOM=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX_GPIO=y
+CONFIG_I2C_MUX_PCA954x=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_IMX=y
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_SABRESD_MAX8903=y
+CONFIG_SENSORS_MAX17135=y
+CONFIG_SENSORS_MAG3110=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_IMX_THERMAL=y
+CONFIG_DEVICE_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_DA9052_I2C=y
+CONFIG_MFD_MC13XXX_SPI=y
+CONFIG_MFD_MC13XXX_I2C=y
+CONFIG_MFD_MAX17135=y
+CONFIG_MFD_SI476X_CORE=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_ANATOP=y
+CONFIG_REGULATOR_DA9052=y
+CONFIG_REGULATOR_MAX17135=y
+CONFIG_REGULATOR_MC13783=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_REGULATOR_PFUZE100=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_RADIO_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_MXC_OUTPUT=y
+CONFIG_VIDEO_MXC_CAPTURE=y
+CONFIG_MXC_CAMERA_OV5640=m
+CONFIG_MXC_CAMERA_OV5642=m
+CONFIG_MXC_CAMERA_OV5640_MIPI=m
+CONFIG_MXC_TVIN_ADV7180=m
+CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=y
+CONFIG_VIDEO_MXC_IPU_OUTPUT=y
+CONFIG_VIDEO_MXC_PXP_V4L2=y
+CONFIG_VIDEO_MXC_CSI_CAMERA=m
+CONFIG_SOC_CAMERA=y
+CONFIG_VIDEO_MX3=y
+CONFIG_RADIO_SI476X=y
+CONFIG_SOC_CAMERA_OV2640=y
+CONFIG_DRM=y
+CONFIG_DRM_VIVANTE=y
+CONFIG_FB=y
+CONFIG_FB_MXS=y
+CONFIG_FB_MXC_SYNC_PANEL=y
+CONFIG_FB_MXC_MIPI_DSI=y
+CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y
+CONFIG_FB_MXC_LDB=y
+CONFIG_FB_MXC_HDMI=y
+CONFIG_FB_MXS_SII902X=y
+CONFIG_HANNSTAR_CABC=y
+CONFIG_FB_MXC_EINK_PANEL=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_L4F00242T03=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_SND_SOC_IMX_CS42888=y
+CONFIG_SND_SOC_IMX_WM8962=y
+CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_SPDIF=y
+CONFIG_SND_SOC_IMX_MC13783=y
+CONFIG_SND_SOC_IMX_SI476X=y
+CONFIG_SND_SOC_IMX_HDMI=y
+CONFIG_SND_SOC_IMX_WM8731=y
+CONFIG_USB=y
+CONFIG_USB_OTG=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_FSL_USB2=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_GADGET_UAC1=y
+CONFIG_USB_ETH=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_MXC_IPU=y
+CONFIG_MXC_GPU_VIV=m
+CONFIG_MXC_MIPI_CSI2=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_EM3027=y
+CONFIG_RTC_DRV_MC13XXX=y
+CONFIG_RTC_DRV_MXC=y
+CONFIG_RTC_DRV_SNVS=y
+CONFIG_DMADEVICES=y
+CONFIG_MXC_PXP_V2=y
+CONFIG_IMX_SDMA=y
+CONFIG_MXS_DMA=y
+CONFIG_STAGING=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PWM=y
+CONFIG_PWM_IMX=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTS=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=y
+CONFIG_CRYPTO_XTS=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=y
+CONFIG_CRYPTO_RMD160=y
+CONFIG_CRYPTO_RMD256=y
+CONFIG_CRYPTO_RMD320=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_CAMELLIA=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index f834eda..7e7e40d 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -680,6 +680,12 @@ config SOC_LS1021A
 	help
 	  This enables support for Freescale LS1021A processor.
 
+config MACH_CM_FX6
+	bool "CompuLab CM-FX6 Support"
+
+	help
+	  This enable support for CompuLab CM-FX6 board.
+
 endif
 
 source "arch/arm/mach-imx/devices/Kconfig"
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index d32d2aa..7d7bcfe 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -127,6 +127,7 @@ obj-$(CONFIG_SOC_IMX7) += pm-imx7.o  ddr3_freq_imx7d.o smp_wfe.o lpddr3_freq_imx
 obj-$(CONFIG_SOC_IMX50) += mach-imx50.o
 obj-$(CONFIG_SOC_IMX51) += mach-imx51.o
 obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
+obj-$(CONFIG_MACH_CM_FX6) += mach-cm_fx6.o
 
 obj-$(CONFIG_SOC_VF610) += clk-vf610.o mach-vf610.o
 
diff --git a/arch/arm/mach-imx/mach-cm_fx6.c b/arch/arm/mach-imx/mach-cm_fx6.c
new file mode 100644
index 0000000..6b540f6
--- /dev/null
+++ b/arch/arm/mach-imx/mach-cm_fx6.c
@@ -0,0 +1,134 @@
+/*
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/regmap.h>
+#include "common.h"
+#include "hardware.h"
+#include <linux/string.h>
+
+
+extern unsigned int system_rev;
+static unsigned int _system_rev;
+
+#define ANADIG_DIGPROG		0x260
+#define ANADIG_DIGPROG_IMX6SL	0x280
+
+extern unsigned int __mxc_cpu_type;
+
+static void revision_from_anatop(void)
+{
+	struct device_node *np;
+	void __iomem *anatop_base;
+	u32 cpu_type;
+	u16 offset = ANADIG_DIGPROG;
+	u32 fsl_system_rev = 0;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
+	anatop_base = of_iomap(np, 0);
+	WARN_ON(!anatop_base);
+	if (of_device_is_compatible(np, "fsl,imx6sl-anatop"))
+		offset = ANADIG_DIGPROG_IMX6SL;
+	cpu_type = readl_relaxed(anatop_base + offset);
+	iounmap(anatop_base);
+
+	/* Chip Silicon ID */
+	fsl_system_rev = ((cpu_type >> 16) & 0xFF) << 12;
+	/* Chip silicon major revision */
+	fsl_system_rev |= ((cpu_type >> 8) & 0xFF) << 4;
+	fsl_system_rev += 0x10;
+	/* Chip silicon minor revision */
+	fsl_system_rev |= cpu_type & 0xFF;
+
+	/*
+	 * Move the CompuLab board revision to a different variable,
+	 * so we can use it anytime it is needed.
+	 * Put the Freescale silicon revision information to the place where
+	 * the userspace video libraries expect it to be.
+	 */
+	system_rev = fsl_system_rev;
+}
+
+static void __init cm_fx6_csi_mux_init(void)
+{
+	/*
+	 * MX6Q sbc-fx6 board:
+	 * IPU1 CSI0 connects to parallel interface.
+	 * Set GPR1 bit 19 to 0x1.
+	 *
+	 * MX6DL sbc-fx6 board:
+	 * IPU1 CSI0 connects to parallel interface.
+	 * Set GPR13 bit 0-2 to 0x4.
+	 */
+	struct regmap *gpr;
+	struct device_node *np;
+	const char *status;
+	int ret;
+
+	/* Read mipi-csi status and set IPU1 CSI0 accordingly */
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mipi-csi2");
+	if (np) {
+		ret = of_property_read_string(np, "status", &status);
+		if (!ret && (!strcasecmp(status, "okay"))) {
+			pr_info("IPU1 CSI0 is in mipi mode\n");
+			return;
+		}
+	}
+
+	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+	if (!IS_ERR(gpr)) {
+		pr_info("IPU1 CSI0 is in parallel mode\n");
+		if (of_machine_is_compatible("fsl,imx6q"))
+			regmap_update_bits(gpr, IOMUXC_GPR1, 1 << 19, 1 << 19);
+		else if (of_machine_is_compatible("fsl,imx6dl"))
+			regmap_update_bits(gpr, IOMUXC_GPR13, 0x7, 0x4);
+	} else {
+		pr_err("%s(): failed to find fsl,imx6q-iomux-gpr regmap\n",
+		       __func__);
+	}
+}
+
+
+static int cm_fx6_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "compulab,cm-fx6");
+
+	if (!np)
+		return -EINVAL;
+
+	_system_rev = system_rev;
+	revision_from_anatop();
+	cm_fx6_csi_mux_init();
+
+	return 0;
+}
+
+static void __exit cm_fx6_exit(void)
+{
+	system_rev = _system_rev;
+}
+module_init(cm_fx6_init);
+module_exit(cm_fx6_exit);
+
+MODULE_AUTHOR("CompuLab, Ltd.");
+MODULE_DESCRIPTION("CompuLab CM-FX6 machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:cm-fx6");
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 7403de9..89db6d7 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -23,6 +23,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/pm_domain.h>
 #include <linux/idr.h>
+#include <linux/i2c.h>
 #include <linux/acpi.h>
 #include <linux/clk/clk-conf.h>
 #include <linux/limits.h>
@@ -502,12 +503,43 @@ err_alloc:
 }
 EXPORT_SYMBOL_GPL(platform_device_register_full);
 
+static int platform_drv_check_dep(struct device_node *of_node)
+{
+	struct device_node *np;
+	struct platform_device *pdev;
+	struct i2c_client *client;
+	const char *depends;
+	int ret;
+
+	depends = of_get_property(of_node, "depends", NULL);
+	if (!depends)
+		return 0;
+
+	np = of_find_node_by_path(depends);
+	if (!np)
+		return 1;
+
+	pdev=of_find_device_by_node(np);
+	if (!pdev) {
+		client = of_find_i2c_device_by_node(np);
+		ret = (!client || !client->dev.driver);
+	} else {
+		ret = (!pdev || !pdev->dev.driver);
+	}
+
+	of_node_put(np);
+	return ret;
+}
+
 static int platform_drv_probe(struct device *_dev)
 {
 	struct platform_driver *drv = to_platform_driver(_dev->driver);
 	struct platform_device *dev = to_platform_device(_dev);
 	int ret;
 
+	if (platform_drv_check_dep(dev->dev.of_node))
+		return -EPROBE_DEFER;
+
 	ret = of_clk_set_defaults(_dev->of_node, false);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 01d6da5..c887ba5 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -198,9 +198,11 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
 	/* Marvell SD8787 Bluetooth device */
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
 			.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
+#ifdef SD8787_AMP
 	/* Marvell SD8787 Bluetooth AMP device */
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911B),
 			.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
+#endif
 	/* Marvell SD8797 Bluetooth device */
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
 			.driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c
index 7ced643..728006e 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.c
@@ -5394,6 +5394,9 @@ gckHARDWARE_SetPowerManagementState(
         /* Force the command queue to reload the next context. */
         command->currContext = gcvNULL;
 
+        /* Trigger a possible dummy draw. */
+        command->dummyDraw = gcvTRUE;
+
         /* Need to config mmu after command start. */
         configMmu = gcvTRUE;
     }
@@ -7354,6 +7357,15 @@ gckHARDWARE_IsFeatureAvailable(
         }
         break;
 
+    /* Only available for v60.*/
+    case gcvFEATURE_USC_DEFER_FILL_FIX:
+        available = gcvFALSE;
+        break;
+
+    case gcvFEATURE_USC:
+        available = gcvFALSE;
+        break;
+
     default:
         gcmkFATAL("Invalid feature has been requested.");
         available = gcvFALSE;
@@ -8472,10 +8484,11 @@ gckHARDWARE_DummyDraw(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
     IN gctUINT32 Address,
+    IN gceDUMMY_DRAW_TYPE DummyDrawType,
     IN OUT gctUINT32 * Bytes
     )
 {
-    gctUINT32 dummyDraw[] = {
+    gctUINT32 dummyDraw_gc400[] = {
 
         ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
         | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0193) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
@@ -8597,14 +8610,41 @@ gckHARDWARE_DummyDraw(
         ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:0) - (0 ? 23:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:0) - (0 ? 23:0) + 1))))))) << (0 ? 23:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:0) - (0 ? 23:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:0) - (0 ? 23:0) + 1))))))) << (0 ? 23:0))),
         };
 
-    dummyDraw[1] = Address;
+    gctUINT32 dummyDraw_v60[] = {
+
+        /* disbale first.*/
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))),
+        ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+
+    };
+
+    gctUINT32 bytes = 0;
+    gctUINT32_PTR dummyDraw = gcvNULL;
+
+
+    switch(DummyDrawType)
+    {
+    case gcvDUMMY_DRAW_GC400:
+        dummyDraw = dummyDraw_gc400;
+        bytes = gcmSIZEOF(dummyDraw_gc400);
+        *(dummyDraw + 1) = Address;
+        break;
+    case gcvDUMMY_DRAW_V60:
+        dummyDraw = dummyDraw_v60;
+        bytes = gcmSIZEOF(dummyDraw_v60);
+        break;
+    default:
+        /* other chip no need dummy draw.*/
+        gcmkASSERT(0);
+        break;
+    };
 
     if (Logical != gcvNULL)
     {
-        gckOS_MemCopy(Logical, dummyDraw, gcmSIZEOF(dummyDraw));
+        gckOS_MemCopy(Logical, dummyDraw, bytes);
     }
 
-    *Bytes = gcmSIZEOF(dummyDraw);
+    *Bytes = bytes;
 
     return gcvSTATUS_OK;
 }
diff --git a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h
index 1c8b1ba..317cb8e 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h
+++ b/drivers/mxc/gpu-viv/hal/kernel/arch/gc_hal_kernel_hardware.h
@@ -212,6 +212,7 @@ gckHARDWARE_DummyDraw(
     IN gckHARDWARE Hardware,
     IN gctPOINTER Logical,
     IN gctUINT32 Address,
+    IN gceDUMMY_DRAW_TYPE DummyDrawType,
     IN OUT gctUINT32 * Bytes
     );
 
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
index 6258f1f..e4d61b5 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
@@ -70,7 +70,7 @@ const char * _VERSION = "\n\0$VERSION$"
                         gcmTXT2STR(gcvVERSION_MAJOR) "."
                         gcmTXT2STR(gcvVERSION_MINOR) "."
                         gcmTXT2STR(gcvVERSION_PATCH) ":"
-                        gcmTXT2STR(gcvVERSION_BUILD) "$\n";
+                        gcmTXT2STR(gcvVERSION_BUILD) "+fslc$\n";
 
 /******************************************************************************\
 ******************************* gckKERNEL API Code ******************************
@@ -285,7 +285,7 @@ _DumpDriverConfigure(
     gcmkPRINT_N(0, "***   GPU DRV CONFIG   ***\n");
     gcmkPRINT_N(0, "**************************\n");
 
-    gcmkPRINT("Galcore version %d.%d.%d.%d\n",
+    gcmkPRINT("Galcore version %d.%d.%d.%d+fslc\n",
               gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
 
     gckOS_DumpParam();
@@ -2503,7 +2503,7 @@ gckKERNEL_Dispatch(
         Interface->u.Version.build = gcvVERSION_BUILD;
 #if gcmIS_DEBUG(gcdDEBUG_TRACE)
         gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
-                       "KERNEL version %d.%d.%d build %u",
+                       "KERNEL version %d.%d.%d build %u (fslc)",
                        gcvVERSION_MAJOR, gcvVERSION_MINOR,
                        gcvVERSION_PATCH, gcvVERSION_BUILD);
 #endif
@@ -2688,6 +2688,12 @@ gckKERNEL_Dispatch(
                                               syncPoint));
                 break;
 
+            case gcvSYNC_POINT_SIGNAL:
+                syncPoint = gcmUINT64_TO_PTR(Interface->u.SyncPoint.syncPoint);
+
+                gcmkONERROR(gckOS_SignalSyncPoint(Kernel->os, syncPoint));
+                break;
+
             default:
                 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
                 break;
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
index 1b4f661..0700ee0 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
@@ -750,6 +750,8 @@ struct _gckCOMMAND
     struct _gckENTRYQUEUE       queue;
 
     gckFENCE                    fence;
+
+    gctBOOL                     dummyDraw;
 };
 
 typedef struct _gcsEVENT *      gcsEVENT_PTR;
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
index b43143b..7aaedd0 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
@@ -463,7 +463,18 @@ _DummyDraw(
 
     gctUINT32 dummyDrawBytes;
 
-    gckHARDWARE_DummyDraw(hardware, gcvNULL, Command->queues[0].address, &dummyDrawBytes);
+    gceDUMMY_DRAW_TYPE dummyDrawType = gcvDUMMY_DRAW_INVALID;
+
+    if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_FE_NEED_DUMMYDRAW))
+    {
+        dummyDrawType = gcvDUMMY_DRAW_GC400;
+    }
+
+    /* 5.0.11 not support v60.*/
+
+    if (dummyDrawType != gcvDUMMY_DRAW_INVALID)
+    {
+        gckHARDWARE_DummyDraw(hardware, gcvNULL, Command->queues[0].address, dummyDrawType, &dummyDrawBytes);
 
     /* Reserve space. */
     gcmkONERROR(gckCOMMAND_Reserve(
@@ -473,9 +484,10 @@ _DummyDraw(
         &bufferSize
         ));
 
-    gckHARDWARE_DummyDraw(hardware, pointer, Command->queues[0].address, &dummyDrawBytes);
+        gckHARDWARE_DummyDraw(hardware, pointer, Command->queues[0].address, dummyDrawType, &dummyDrawBytes);
 
     gcmkONERROR(gckCOMMAND_Execute(Command, dummyDrawBytes));
+    }
 
     return gcvSTATUS_OK;
 OnError:
@@ -710,6 +722,8 @@ gckCOMMAND_Construct(
     command->queue.rear = 0;
     command->queue.count = 0;
 
+    command->dummyDraw = gcvTRUE;
+
     /* Return pointer to the gckCOMMAND object. */
     *Command = command;
 
@@ -1516,8 +1530,10 @@ gckCOMMAND_Commit(
 
     gcmkONERROR(_FlushMMU(Command));
 
-    if (gckHARDWARE_IsFeatureAvailable(hardware, gcvFEATURE_FE_NEED_DUMMYDRAW) && Command->currContext == gcvNULL)
+    if (Command->dummyDraw == gcvTRUE &&
+        Context != gcvNULL)
     {
+        Command->dummyDraw = gcvFALSE;
         gcmkONERROR(_DummyDraw(Command));
     }
 
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
index ed209a3..7042ef4 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
@@ -1609,15 +1609,27 @@ _TaskSignal(
 
         /* Map the signal into kernel space. */
 #ifdef __QNXNTO__
-        gcmkERR_BREAK(gckOS_UserSignal(
+        status = gckOS_UserSignal(
             Command->os, task->signal, task->rcvid, task->coid
-            ));
+            );
 #else
-        gcmkERR_BREAK(gckOS_UserSignal(
+        status = gckOS_UserSignal(
             Command->os, task->signal, task->process
-            ));
+            );
 #endif /* __QNXNTO__ */
 
+        if (gcmIS_ERROR(status))
+        {
+            if (status == gcvSTATUS_NOT_FOUND)
+            {
+                status = gcvSTATUS_OK;
+            }
+            else
+            {
+                break;
+            }
+        }
+
         /* Update the reference counter. */
         TaskHeader->container->referenceCount -= 1;
 
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
index 1c3eaa6..29144a2 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
@@ -94,6 +94,7 @@ gckKERNEL_NewDatabase(
     gctBOOL acquired = gcvFALSE;
     gctSIZE_T slot;
     gcsDATABASE_PTR existingDatabase;
+    gctPOINTER pointer = gcvNULL;
 
     gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
 
@@ -124,8 +125,6 @@ gckKERNEL_NewDatabase(
     }
     else
     {
-        gctPOINTER pointer = gcvNULL;
-
         /* Allocate a new database from the heap. */
         gcmkONERROR(gckOS_Allocate(Kernel->os,
                                    gcmSIZEOF(gcsDATABASE),
@@ -156,6 +155,11 @@ gckKERNEL_NewDatabase(
     return gcvSTATUS_OK;
 
 OnError:
+    if (pointer)
+    {
+        gcmkVERIFY_OK(gckOS_Free(Kernel->os,pointer));
+    }
+
     if (acquired)
     {
         /* Release the database mutex. */
@@ -1485,6 +1489,9 @@ gckKERNEL_DestroyProcessDB(
             break;
 
         case gcvDB_MAP_USER_MEMORY:
+
+            gcmkERR_BREAK(gckCOMMAND_Stall(Kernel->command, gcvFALSE));
+
             /* TODO: Unmap user memory. */
             status = gckOS_UnmapUserMemory(Kernel->os,
                                            Kernel->core,
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
index b78fb65..1443fcc 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c
@@ -481,29 +481,29 @@ gceSTATUS gckVGKERNEL_Dispatch(
         break;
 
     case gcvHAL_FREE_NON_PAGED_MEMORY:
-        physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
+        physical = gcmNAME_TO_PTR(kernelInterface->u.FreeNonPagedMemory.physical);
 
         /* Unmap user logical out of physical memory first. */
         gcmkERR_BREAK(gckOS_UnmapUserLogical(
             Kernel->os,
             physical,
-            (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
-            gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
+            (gctSIZE_T) kernelInterface->u.FreeNonPagedMemory.bytes,
+            gcmUINT64_TO_PTR(kernelInterface->u.FreeNonPagedMemory.logical)
             ));
 
         /* Free non-paged memory. */
         gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
             Kernel->os,
-            (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
+            (gctSIZE_T) kernelInterface->u.FreeNonPagedMemory.bytes,
             physical,
-            gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
+            gcmUINT64_TO_PTR(kernelInterface->u.FreeNonPagedMemory.logical)
             ));
 
-        gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
+        gcmRELEASE_NAME(kernelInterface->u.FreeNonPagedMemory.physical);
         break;
 
     case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
-        bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes;
+        bytes = (gctSIZE_T) kernelInterface->u.AllocateContiguousMemory.bytes;
         /* Allocate contiguous memory. */
         gcmkERR_BREAK(gckOS_AllocateContiguous(
             Kernel->os,
@@ -513,30 +513,30 @@ gceSTATUS gckVGKERNEL_Dispatch(
             &logical
             ));
 
-        kernelInterface->u.AllocateNonPagedMemory.bytes    = bytes;
-        kernelInterface->u.AllocateNonPagedMemory.logical  = gcmPTR_TO_UINT64(logical);
-        kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
+        kernelInterface->u.AllocateContiguousMemory.bytes    = bytes;
+        kernelInterface->u.AllocateContiguousMemory.logical  = gcmPTR_TO_UINT64(logical);
+        kernelInterface->u.AllocateContiguousMemory.physical = gcmPTR_TO_NAME(physical);
         break;
 
     case gcvHAL_FREE_CONTIGUOUS_MEMORY:
-        physical = gcmNAME_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.physical);
+        physical = gcmNAME_TO_PTR(kernelInterface->u.FreeContiguousMemory.physical);
         /* Unmap user logical out of physical memory first. */
         gcmkERR_BREAK(gckOS_UnmapUserLogical(
             Kernel->os,
             physical,
-            (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes,
-            gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical)
+            (gctSIZE_T) kernelInterface->u.FreeContiguousMemory.bytes,
+            gcmUINT64_TO_PTR(kernelInterface->u.FreeContiguousMemory.logical)
             ));
 
         /* Free contiguous memory. */
         gcmkERR_BREAK(gckOS_FreeContiguous(
             Kernel->os,
             physical,
-            gcmUINT64_TO_PTR(kernelInterface->u.AllocateNonPagedMemory.logical),
-            (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes
+            gcmUINT64_TO_PTR(kernelInterface->u.FreeContiguousMemory.logical),
+            (gctSIZE_T) kernelInterface->u.FreeContiguousMemory.bytes
             ));
 
-        gcmRELEASE_NAME(kernelInterface->u.AllocateNonPagedMemory.physical);
+        gcmRELEASE_NAME(kernelInterface->u.FreeContiguousMemory.physical);
         break;
 
     case gcvHAL_ALLOCATE_VIDEO_MEMORY:
@@ -576,6 +576,8 @@ gceSTATUS gckVGKERNEL_Dispatch(
             gckVIDMEM_HANDLE_Lookup(Kernel, processID,
                                     (gctUINT32)kernelInterface->u.ReleaseVideoMemory.node, &nodeObject));
 
+        gckVIDMEM_HANDLE_Dereference(Kernel, processID,(gctUINT32)Interface->u.ReleaseVideoMemory.node);
+
         gckVIDMEM_NODE_Dereference(Kernel, nodeObject);
     }
 
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
index b6694c7..1b0d542 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
@@ -55,6 +55,14 @@
 
 #include "gc_hal_kernel_precomp.h"
 
+#if defined(__QNXNTO__)
+#include <stdlib.h>
+#include <sys/slogcodes.h>
+#include <time.h>
+
+extern unsigned int slogUsageInterval;
+#endif
+
 #define _GC_OBJ_ZONE    gcvZONE_VIDMEM
 
 /******************************************************************************\
@@ -896,7 +904,29 @@ gckVIDMEM_AllocateLinear(
     gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
 
     acquired = gcvTRUE;
+#if defined(__QNXNTO__)
+    if (slogUsageInterval > 0) {
+        static gctSIZE_T lowwaterFPC = ~0;
+        static time_t last_slog_time;
+        int do_slog_now = 0;
+        time_t this_slog_time = time(NULL);
+
+        if (Memory->freeBytes < lowwaterFPC) {
+            do_slog_now = 1;
+            lowwaterFPC = Memory->freeBytes;
+        }
 
+        if (abs(this_slog_time - last_slog_time) > slogUsageInterval) {
+            do_slog_now = 1;
+        }
+
+        if (do_slog_now) {
+            last_slog_time = this_slog_time;
+            slogf(_SLOGC_GRAPHICS_GL, _SLOG_INFO, "%s: Memory->freeBytes = %u, lowest Memory->freeBytes = %u",
+                    __FUNCTION__, (unsigned) Memory->freeBytes, (unsigned) lowwaterFPC);
+        }
+    }
+#endif
     if (Bytes > Memory->freeBytes)
     {
         /* Not enough memory. */
@@ -2611,6 +2641,7 @@ gckVIDMEM_NODE_Dereference(
 #endif
         gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Node->mutex));
         gcmkOS_SAFE_FREE(Kernel->os, Node);
+        Node = NULL;
     }
 
     gcmkFOOTER_NO();
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
index 85700c5..b53f738 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
@@ -326,12 +326,24 @@ typedef enum _gceFEATURE
 
     gcvFEATURE_PE_ENHANCEMENTS2,
     gcvFEATURE_FE_NEED_DUMMYDRAW,
+    gcvFEATURE_USC_DEFER_FILL_FIX,
+    gcvFEATURE_USC,
 
     /* Insert features above this comment only. */
     gcvFEATURE_COUNT                /* Not a feature. */
 }
 gceFEATURE;
 
+/* dummy draw type.*/
+typedef enum _gceDUMMY_DRAW_TYPE
+{
+    gcvDUMMY_DRAW_INVALID = 0,
+    gcvDUMMY_DRAW_GC400,
+    gcvDUMMY_DRAW_V60,
+}
+gceDUMMY_DRAW_TYPE;
+
+
 /* Chip SWWA. */
 typedef enum _gceSWWA
 {
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c
index 43203f7..cea2e8b 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c
@@ -164,6 +164,11 @@ _DmabufAttach(
     return gcvSTATUS_OK;
 
 OnError:
+    if(pagearray)
+    {
+        gcmkVERIFY_OK(gckOS_Free(os, (gctPOINTER)pagearray));
+    }
+
     gcmkFOOTER();
     return status;
 }
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c
index a0d7840..7d759ff 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/allocator/freescale/gc_hal_kernel_allocator_cma.c
@@ -441,6 +441,11 @@ _CMAFSLAlloctorInit(
     return gcvSTATUS_OK;
 
 OnError:
+    if(allocator)
+    {
+        gcmkVERIFY_OK(gckOS_Free(Os, (gctPOINTER)allocator));
+    }
+
     return status;
 }
 
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c
index 93d6fa8..55de406 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_allocator.c
@@ -799,6 +799,10 @@ _DefaultAlloctorInit(
     return gcvSTATUS_OK;
 
 OnError:
+    if(allocator)
+    {
+        gcmkVERIFY_OK(gckOS_Free(Os, (gctPOINTER)allocator));
+    }
     return status;
 }
 
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
index 92e7ebc..2f2fa2b 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
@@ -382,7 +382,7 @@ gc_version_show(struct seq_file *m, void *data)
     gcsPLATFORM * platform = device->platform;
     gctCONST_STRING name;
 
-    seq_printf(m, "%s built at %s\n",  gcvVERSION_STRING, HOST);
+    seq_printf(m, "%s+fslc built at %s\n",  gcvVERSION_STRING, HOST);
 
     if (platform->ops->name)
     {
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
index c3f9170..886acff 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
@@ -6886,6 +6886,9 @@ gckOS_QueryProfileTickRate(
     OUT gctUINT64_PTR TickRate
     )
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0)
+    *TickRate = hrtimer_resolution;
+#else
     struct timespec res;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
@@ -6896,6 +6899,7 @@ gckOS_QueryProfileTickRate(
 #endif
 
     *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
+#endif
 
     return gcvSTATUS_OK;
 }
@@ -7382,7 +7386,11 @@ gckOS_WaitSignal(
 
     might_sleep();
 
+#ifdef CONFIG_PREEMPT_RT_BASE
+    raw_spin_lock_irq(&signal->obj.wait.lock);
+#else
     spin_lock_irq(&signal->obj.wait.lock);
+#endif
 
     if (signal->obj.done)
     {
@@ -7404,9 +7412,14 @@ gckOS_WaitSignal(
             ? MAX_SCHEDULE_TIMEOUT
             : Wait * HZ / 1000;
 
+#ifdef CONFIG_PREEMPT_RT_BASE
+        DEFINE_SWAITER(wait);
+        swait_prepare_locked(&signal->obj.wait, &wait);
+#else
         DECLARE_WAITQUEUE(wait, current);
         wait.flags |= WQ_FLAG_EXCLUSIVE;
         __add_wait_queue_tail(&signal->obj.wait, &wait);
+#endif
 
         while (gcvTRUE)
         {
@@ -7418,9 +7431,15 @@ gckOS_WaitSignal(
             }
 
             __set_current_state(TASK_INTERRUPTIBLE);
+#ifdef CONFIG_PREEMPT_RT_BASE
+            raw_spin_unlock_irq(&signal->obj.wait.lock);
+            timeout = schedule_timeout(timeout);
+            raw_spin_lock_irq(&signal->obj.wait.lock);
+#else
             spin_unlock_irq(&signal->obj.wait.lock);
             timeout = schedule_timeout(timeout);
             spin_lock_irq(&signal->obj.wait.lock);
+#endif
 
             if (signal->obj.done)
             {
@@ -7441,10 +7460,18 @@ gckOS_WaitSignal(
             }
         }
 
+#ifdef CONFIG_PREEMPT_RT_BASE
+        swait_finish_locked(&signal->obj.wait, &wait);
+#else
         __remove_wait_queue(&signal->obj.wait, &wait);
+#endif
     }
 
+#ifdef CONFIG_PREEMPT_RT_BASE
+    raw_spin_unlock_irq(&signal->obj.wait.lock);
+#else
     spin_unlock_irq(&signal->obj.wait.lock);
+#endif
 
 OnError:
     /* Return status. */
@@ -8556,6 +8583,16 @@ OnError:
     return status;
 }
 
+static void
+_NativeFenceSignaled(
+    struct sync_fence *fence,
+    struct sync_fence_waiter *waiter
+    )
+{
+    kfree(waiter);
+    sync_fence_put(fence);
+}
+
 gceSTATUS
 gckOS_WaitNativeFence(
     IN gckOS Os,
@@ -8566,7 +8603,7 @@ gckOS_WaitNativeFence(
 {
     struct sync_timeline * timeline;
     struct sync_fence * fence;
-    gctBOOL wait = gcvFALSE;
+    gctBOOL wait;
     gceSTATUS status = gcvSTATUS_OK;
 
     gcmkHEADER_ARG("Os=0x%X Timeline=0x%X FenceFD=%d Timeout=%u",
@@ -8583,6 +8620,17 @@ gckOS_WaitNativeFence(
         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
     }
 
+    if (sync_fence_wait(fence, 0) == 0)
+    {
+        /* Already signaled. */
+        sync_fence_put(fence);
+
+        gcmkFOOTER_NO();
+        return gcvSTATUS_OK;
+    }
+
+    wait = gcvFALSE;
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
     {
         int i;
@@ -8624,6 +8672,9 @@ gckOS_WaitNativeFence(
         long timeout = (Timeout == gcvINFINITE) ? - 1 : (long) Timeout;
         err = sync_fence_wait(fence, timeout);
 
+        /* Put the fence. */
+        sync_fence_put(fence);
+
         switch (err)
         {
         case 0:
@@ -8633,11 +8684,44 @@ gckOS_WaitNativeFence(
             break;
         default:
             gcmkONERROR(gcvSTATUS_GENERIC_IO);
+            break;
         }
     }
+    else
+    {
+        int err;
+        struct sync_fence_waiter *waiter;
+        waiter = (struct sync_fence_waiter *)kmalloc(
+                sizeof (struct sync_fence_waiter), gcdNOWARN | GFP_KERNEL);
 
-    /* Put the fence. */
-    sync_fence_put(fence);
+        if (!waiter)
+        {
+            sync_fence_put(fence);
+            gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+        }
+
+        /* Schedule a waiter callback. */
+        sync_fence_waiter_init(waiter, _NativeFenceSignaled);
+        err = sync_fence_wait_async(fence, waiter);
+
+        switch (err)
+        {
+        case 0:
+            /* Put fence in callback function. */
+            break;
+        case 1:
+            /* already signaled. */
+            sync_fence_put(fence);
+            break;
+        default:
+            sync_fence_put(fence);
+            gcmkONERROR(gcvSTATUS_GENERIC_IO);
+            break;
+        }
+    }
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
 
 OnError:
     gcmkFOOTER();
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c
index e436ada..dc7c976 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c
@@ -119,6 +119,7 @@ struct platform_device *pdevice;
 #    include <linux/mm.h>
 #    include <linux/oom.h>
 #    include <linux/sched.h>
+#    include <linux/profile.h>
 
 struct task_struct *lowmem_deathpending;
 
@@ -137,7 +138,7 @@ task_notify_func(struct notifier_block *self, unsigned long val, void *data)
 	if (task == lowmem_deathpending)
 		lowmem_deathpending = NULL;
 
-	return NOTIFY_OK;
+	return NOTIFY_DONE;
 }
 
 extern struct task_struct *lowmem_deathpending;
@@ -475,8 +476,10 @@ gckPLATFORM_AdjustParam(
 
     Args->gpu3DMinClock = initgpu3DMinClock;
 
-  if(Args->physSize == 0)
-    Args->physSize = 0x80000000;
+    if(Args->physSize == 0)
+    {
+        Args->physSize = 0x80000000;
+    }
 
     return gcvSTATUS_OK;
 }
@@ -489,7 +492,11 @@ _AllocPriv(
     Platform->priv = &imxPriv;
 
 #ifdef CONFIG_GPU_LOW_MEMORY_KILLER
-    task_free_register(&task_nb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+     task_free_register(&task_nb);
+#else
+    task_handoff_register(&task_nb);
+#endif
 #endif
 
     return gcvSTATUS_OK;
@@ -501,7 +508,11 @@ _FreePriv(
     )
 {
 #ifdef CONFIG_GPU_LOW_MEMORY_KILLER
-    task_free_unregister(&task_nb);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0)
+     task_free_unregister(&task_nb);
+#else
+    task_handoff_unregister(&task_nb);
+#endif
 #endif
 
     return gcvSTATUS_OK;
@@ -628,7 +639,7 @@ _GetPower(
     }
 
 
-#if gcdENABLE_FSCALE_VAL_ADJUST
+#if gcdENABLE_FSCALE_VAL_ADJUST && defined(CONFIG_DEVICE_THERMAL)
     pdevice = Platform->device;
     REG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
     {
@@ -692,7 +703,7 @@ _PutPower(
     }
 #endif
 
-#if gcdENABLE_FSCALE_VAL_ADJUST
+#if gcdENABLE_FSCALE_VAL_ADJUST && defined(CONFIG_DEVICE_THERMAL)
     UNREG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier);
 
     driver_remove_file(pdevice->dev.driver, &driver_attr_gpu3DMinClock);
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config
index 0b2cb43..1a520e9 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.config
@@ -3,7 +3,7 @@ EXTRA_CFLAGS += -DgcdFSL_CONTIGUOUS_SIZE=134217728
 
 ifneq ($(CONFIG_ANDROID),)
 # build for android
-EXTRA_CFLAGS += -DgcdANDROID_NATIVE_FENCE_SYNC=3
+EXTRA_CFLAGS += -DgcdANDROID_NATIVE_FENCE_SYNC=2
 
 ifeq ($(CONFIG_SYNC),)
 $(warn CONFIG_SYNC is not set in kernel config)
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 7dfbcde..cf579f9 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2430,6 +2430,11 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (hw->mac.ops.read_mac_addr(hw))
 		dev_err(&pdev->dev, "NVM Read Error\n");
 
+	if (!is_valid_ether_addr(hw->mac.addr)) {
+		dev_info(&pdev->dev, "Random MAC Address\n");
+		random_ether_addr(hw->mac.addr);
+	}
+
 	memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len);
 
 	if (!is_valid_ether_addr(netdev->dev_addr)) {
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 20c1332..8b91ea2 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -163,6 +163,18 @@ void of_device_unregister(struct platform_device *ofdev)
 }
 EXPORT_SYMBOL(of_device_unregister);
 
+const void *of_device_get_match_data(const struct device *dev)
+{
+	const struct of_device_id *match;
+
+	match = of_match_device(dev->driver->of_match_table, dev);
+	if (!match)
+		return NULL;
+
+	return match->data;
+}
+EXPORT_SYMBOL(of_device_get_match_data);
+
 ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
 {
 	const char *compat;
diff --git a/drivers/reset/gpio-reset.c b/drivers/reset/gpio-reset.c
index 4cb9929..2314c6c 100644
--- a/drivers/reset/gpio-reset.c
+++ b/drivers/reset/gpio-reset.c
@@ -21,6 +21,7 @@ struct gpio_reset_data {
 	unsigned int gpio;
 	bool active_low;
 	s32 delay_us;
+	void (*gpio_set_value)(unsigned, int);
 };
 
 static void gpio_reset_set(struct reset_controller_dev *rcdev, int asserted)
@@ -32,7 +33,7 @@ static void gpio_reset_set(struct reset_controller_dev *rcdev, int asserted)
 	if (drvdata->active_low)
 		value = !value;
 
-	gpio_set_value(drvdata->gpio, value);
+	drvdata->gpio_set_value(drvdata->gpio, value);
 }
 
 static int gpio_reset(struct reset_controller_dev *rcdev, unsigned long id)
@@ -122,6 +123,11 @@ static int gpio_reset_probe(struct platform_device *pdev)
 	else
 		gpio_flags = GPIOF_OUT_INIT_LOW;
 
+	if (of_get_property(np, "gpio-can-sleep", NULL))
+		drvdata->gpio_set_value = gpio_set_value_cansleep;
+	else
+		drvdata->gpio_set_value = gpio_set_value;
+
 	ret = devm_gpio_request_one(&pdev->dev, drvdata->gpio, gpio_flags, NULL);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to request gpio %d: %d\n",
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 8cd3534..5400f82 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -571,9 +571,11 @@ config BFIN_UART3_CTSRTS
 
 config SERIAL_IMX
 	tristate "IMX serial port support"
-	depends on ARCH_MXC
+	depends on HAS_DMA
+	depends on ARCH_MXC || COMPILE_TEST
 	select SERIAL_CORE
 	select RATIONAL
+	select SERIAL_MCTRL_GPIO if GPIOLIB
 	help
 	  If you have a machine based on a Motorola IMX CPU you
 	  can enable its onboard serial port by enabling this option.
@@ -582,6 +584,7 @@ config SERIAL_IMX_CONSOLE
 	bool "Console on IMX serial port"
 	depends on SERIAL_IMX=y
 	select SERIAL_CORE_CONSOLE
+	select SERIAL_EARLYCON if OF
 	help
 	  If you have enabled the serial port on the Freescale IMX
 	  CPU you can make it the console by answering Y to this option.
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index c9bd603..231e7d5 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -44,6 +44,8 @@
 #include <linux/platform_data/serial-imx.h>
 #include <linux/platform_data/dma-imx.h>
 
+#include "serial_mctrl_gpio.h"
+
 /* Register definitions */
 #define URXD0 0x0  /* Receiver Register */
 #define URTX0 0x40 /* Transmitter Register */
@@ -139,7 +141,7 @@
 #define USR1_ESCF	(1<<11) /* Escape seq interrupt flag */
 #define USR1_FRAMERR	(1<<10) /* Frame error interrupt flag */
 #define USR1_RRDY	(1<<9)	 /* Receiver ready interrupt/dma flag */
-#define USR1_AGTIM	(1<<8)   /* Ageing timer interrfupt flag */
+#define USR1_AGTIM	(1<<8)	 /* Ageing timer interrupt flag */
 #define USR1_TIMEOUT	(1<<7)	 /* Receive timeout interrupt status */
 #define USR1_RXDS	 (1<<6)	 /* Receiver idle interrupt flag */
 #define USR1_AIRINT	 (1<<5)	 /* Async IR wake interrupt flag */
@@ -148,8 +150,11 @@
 #define USR2_TXFE	 (1<<14) /* Transmit buffer FIFO empty */
 #define USR2_DTRF	 (1<<13) /* DTR edge interrupt flag */
 #define USR2_IDLE	 (1<<12) /* Idle condition */
+#define USR2_RIDELT	 (1<<10) /* Ring Interrupt Delta */
+#define USR2_RIIN	 (1<<9)	 /* Ring Indicator Input */
 #define USR2_IRINT	 (1<<8)	 /* Serial infrared interrupt flag */
 #define USR2_WAKE	 (1<<7)	 /* Wake */
+#define USR2_DCDIN	 (1<<5)	 /* Data Carrier Detect Input */
 #define USR2_RTSF	 (1<<4)	 /* RTS edge interrupt flag */
 #define USR2_TXDC	 (1<<3)	 /* Transmitter complete */
 #define USR2_BRCD	 (1<<2)	 /* Break condition */
@@ -179,8 +184,6 @@
 #define DRIVER_NAME "IMX-uart"
 
 #define UART_NR 8
-#define IMX_RXBD_NUM 20
-#define IMX_MODULE_MAX_CLK_RATE	80000000
 
 /* i.MX21 type uart runs on all i.mx except i.MX1 and i.MX6q */
 enum imx_uart_type {
@@ -195,24 +198,6 @@ struct imx_uart_data {
 	enum imx_uart_type devtype;
 };
 
-struct imx_dma_bufinfo {
-	bool filled;
-	unsigned int rx_bytes;
-};
-
-struct imx_dma_rxbuf {
-	unsigned int		periods;
-	unsigned int		period_len;
-	unsigned int		buf_len;
-
-	void			*buf;
-	dma_addr_t		dmaaddr;
-	unsigned int		cur_idx;
-	unsigned int		last_completed_idx;
-	dma_cookie_t		cookie;
-	struct imx_dma_bufinfo	buf_info[IMX_RXBD_NUM];
-};
-
 struct imx_port {
 	struct uart_port	port;
 	struct timer_list	timer;
@@ -226,21 +211,21 @@ struct imx_port {
 	struct clk		*clk_per;
 	const struct imx_uart_data *devdata;
 
+	struct mctrl_gpios *gpios;
+
 	/* DMA fields */
 	unsigned int		dma_is_inited:1;
 	unsigned int		dma_is_enabled:1;
 	unsigned int		dma_is_rxing:1;
 	unsigned int		dma_is_txing:1;
 	struct dma_chan		*dma_chan_rx, *dma_chan_tx;
-	struct scatterlist	tx_sgl[2];
-	struct imx_dma_rxbuf	rx_buf;
+	struct scatterlist	rx_sgl, tx_sgl[2];
+	void			*rx_buf;
 	unsigned int		tx_bytes;
 	unsigned int		dma_tx_nents;
-	struct delayed_work	tsk_dma_tx;
 	wait_queue_head_t	dma_wait;
 	unsigned int            saved_reg[10];
-#define DMA_TX_IS_WORKING 1
-	unsigned long		flags;
+	bool			context_saved;
 };
 
 struct imx_port_ucrs {
@@ -264,7 +249,7 @@ static struct imx_uart_data imx_uart_devdata[] = {
 	},
 };
 
-static struct platform_device_id imx_uart_devtype[] = {
+static const struct platform_device_id imx_uart_devtype[] = {
 	{
 		.name = "imx1-uart",
 		.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX1_UART],
@@ -330,49 +315,24 @@ static void imx_port_ucrs_restore(struct uart_port *port,
 }
 #endif
 
-/*
- * Handle any change of modem status signal since we were last called.
- */
-static void imx_mctrl_check(struct imx_port *sport)
+static void imx_port_rts_active(struct imx_port *sport, unsigned long *ucr2)
 {
-	unsigned int status, changed;
-
-	status = sport->port.ops->get_mctrl(&sport->port);
-	changed = status ^ sport->old_status;
-
-	if (changed == 0)
-		return;
-
-	sport->old_status = status;
-
-	if (changed & TIOCM_RI)
-		sport->port.icount.rng++;
-	if (changed & TIOCM_DSR)
-		sport->port.icount.dsr++;
-	if (changed & TIOCM_CAR)
-		uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
-	if (changed & TIOCM_CTS)
-		uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
+	*ucr2 &= ~UCR2_CTSC;
+	*ucr2 |= UCR2_CTS;
 
-	wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
+	mctrl_gpio_set(sport->gpios, sport->port.mctrl | TIOCM_RTS);
 }
 
-/*
- * This is our per-port timeout handler, for checking the
- * modem status signals.
- */
-static void imx_timeout(unsigned long data)
+static void imx_port_rts_inactive(struct imx_port *sport, unsigned long *ucr2)
 {
-	struct imx_port *sport = (struct imx_port *)data;
-	unsigned long flags;
+	*ucr2 &= ~(UCR2_CTSC | UCR2_CTS);
 
-	if (sport->port.state) {
-		spin_lock_irqsave(&sport->port.lock, flags);
-		imx_mctrl_check(sport);
-		spin_unlock_irqrestore(&sport->port.lock, flags);
+	mctrl_gpio_set(sport->gpios, sport->port.mctrl & ~TIOCM_RTS);
+}
 
-		mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
-	}
+static void imx_port_rts_auto(struct imx_port *sport, unsigned long *ucr2)
+{
+	*ucr2 |= UCR2_CTSC;
 }
 
 /*
@@ -398,9 +358,9 @@ static void imx_stop_tx(struct uart_port *port)
 	    readl(port->membase + USR2) & USR2_TXDC) {
 		temp = readl(port->membase + UCR2);
 		if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
-			temp &= ~UCR2_CTS;
+			imx_port_rts_inactive(sport, &temp);
 		else
-			temp |= UCR2_CTS;
+			imx_port_rts_active(sport, &temp);
 		writel(temp, port->membase + UCR2);
 
 		temp = readl(port->membase + UCR4);
@@ -426,14 +386,12 @@ static void imx_stop_rx(struct uart_port *port)
 		}
 	}
 
-	/* disable the Receiver Ready and overrun Interrrupt */
-	temp = readl(sport->port.membase + UCR1);
-	writel(temp & ~UCR1_RRDYEN, sport->port.membase + UCR1);
-	temp = readl(sport->port.membase + UCR4);
-	writel(temp & ~UCR4_OREN, sport->port.membase + UCR4);
-
 	temp = readl(sport->port.membase + UCR2);
 	writel(temp & ~UCR2_RXEN, sport->port.membase + UCR2);
+
+	/* disable the `Receiver Ready Interrrupt` */
+	temp = readl(sport->port.membase + UCR1);
+	writel(temp & ~UCR1_RRDYEN, sport->port.membase + UCR1);
 }
 
 /*
@@ -444,8 +402,11 @@ static void imx_enable_ms(struct uart_port *port)
 	struct imx_port *sport = (struct imx_port *)port;
 
 	mod_timer(&sport->timer, jiffies);
+
+	mctrl_gpio_enable_ms(sport->gpios);
 }
 
+static void imx_dma_tx(struct imx_port *sport);
 static inline void imx_transmit_buffer(struct imx_port *sport)
 {
 	struct circ_buf *xmit = &sport->port.state->xmit;
@@ -476,7 +437,7 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
 			writel(temp, sport->port.membase + UCR1);
 		} else {
 			writel(temp, sport->port.membase + UCR1);
-			schedule_delayed_work(&sport->tsk_dma_tx, 0);
+			imx_dma_tx(sport);
 		}
 	}
 
@@ -502,89 +463,95 @@ static void dma_tx_callback(void *data)
 	struct scatterlist *sgl = &sport->tx_sgl[0];
 	struct circ_buf *xmit = &sport->port.state->xmit;
 	unsigned long flags;
+	unsigned long temp;
+
+	spin_lock_irqsave(&sport->port.lock, flags);
 
 	dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
 
-	sport->dma_is_txing = 0;
+	temp = readl(sport->port.membase + UCR1);
+	temp &= ~UCR1_TDMAEN;
+	writel(temp, sport->port.membase + UCR1);
 
 	/* update the stat */
-	spin_lock_irqsave(&sport->port.lock, flags);
 	xmit->tail = (xmit->tail + sport->tx_bytes) & (UART_XMIT_SIZE - 1);
 	sport->port.icount.tx += sport->tx_bytes;
-	spin_unlock_irqrestore(&sport->port.lock, flags);
 
 	dev_dbg(sport->port.dev, "we finish the TX DMA.\n");
 
-	clear_bit(DMA_TX_IS_WORKING, &sport->flags);
-	smp_mb__after_atomic();
-	uart_write_wakeup(&sport->port);
+	sport->dma_is_txing = 0;
+
+	spin_unlock_irqrestore(&sport->port.lock, flags);
 
-	schedule_delayed_work(&sport->tsk_dma_tx, msecs_to_jiffies(1));
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(&sport->port);
 
 	if (waitqueue_active(&sport->dma_wait)) {
 		wake_up(&sport->dma_wait);
 		dev_dbg(sport->port.dev, "exit in %s.\n", __func__);
 		return;
 	}
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+	if (!uart_circ_empty(xmit) && !uart_tx_stopped(&sport->port))
+		imx_dma_tx(sport);
+	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
-static void dma_tx_work(struct work_struct *w)
+static void imx_dma_tx(struct imx_port *sport)
 {
-	struct delayed_work *delay_work = to_delayed_work(w);
-	struct imx_port *sport = container_of(delay_work, struct imx_port, tsk_dma_tx);
 	struct circ_buf *xmit = &sport->port.state->xmit;
 	struct scatterlist *sgl = sport->tx_sgl;
 	struct dma_async_tx_descriptor *desc;
 	struct dma_chan	*chan = sport->dma_chan_tx;
 	struct device *dev = sport->port.dev;
-	unsigned long flags;
+	unsigned long temp;
 	int ret;
 
-	if (test_and_set_bit(DMA_TX_IS_WORKING, &sport->flags))
+	if (sport->dma_is_txing)
 		return;
 
-	spin_lock_irqsave(&sport->port.lock, flags);
 	sport->tx_bytes = uart_circ_chars_pending(xmit);
 
-	if (sport->tx_bytes > 0) {
-		if (xmit->tail > xmit->head && xmit->head > 0) {
-			sport->dma_tx_nents = 2;
-			sg_init_table(sgl, 2);
-			sg_set_buf(sgl, xmit->buf + xmit->tail,
-					UART_XMIT_SIZE - xmit->tail);
-			sg_set_buf(sgl + 1, xmit->buf, xmit->head);
-		} else {
-			sport->dma_tx_nents = 1;
-			sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes);
-		}
-		spin_unlock_irqrestore(&sport->port.lock, flags);
+	if (xmit->tail < xmit->head) {
+		sport->dma_tx_nents = 1;
+		sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes);
+	} else {
+		sport->dma_tx_nents = 2;
+		sg_init_table(sgl, 2);
+		sg_set_buf(sgl, xmit->buf + xmit->tail,
+				UART_XMIT_SIZE - xmit->tail);
+		sg_set_buf(sgl + 1, xmit->buf, xmit->head);
+	}
 
-		ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
-		if (ret == 0) {
-			dev_err(dev, "DMA mapping error for TX.\n");
-			goto err_out;
-		}
-		desc = dmaengine_prep_slave_sg(chan, sgl, sport->dma_tx_nents,
-						DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
-		if (!desc) {
-			dev_err(dev, "We cannot prepare for the TX slave dma!\n");
-			goto err_out;
-		}
-		desc->callback = dma_tx_callback;
-		desc->callback_param = sport;
-
-		dev_dbg(dev, "TX: prepare to send %lu bytes by DMA.\n",
-				uart_circ_chars_pending(xmit));
-		/* fire it */
-		sport->dma_is_txing = 1;
-		dmaengine_submit(desc);
-		dma_async_issue_pending(chan);
+	ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
+	if (ret == 0) {
+		dev_err(dev, "DMA mapping error for TX.\n");
 		return;
 	}
-	spin_unlock_irqrestore(&sport->port.lock, flags);
-err_out:
-	clear_bit(DMA_TX_IS_WORKING, &sport->flags);
-	smp_mb__after_atomic();
+	desc = dmaengine_prep_slave_sg(chan, sgl, sport->dma_tx_nents,
+					DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
+	if (!desc) {
+		dma_unmap_sg(dev, sgl, sport->dma_tx_nents,
+			     DMA_TO_DEVICE);
+		dev_err(dev, "We cannot prepare for the TX slave dma!\n");
+		return;
+	}
+	desc->callback = dma_tx_callback;
+	desc->callback_param = sport;
+
+	dev_dbg(dev, "TX: prepare to send %lu bytes by DMA.\n",
+			uart_circ_chars_pending(xmit));
+
+	temp = readl(sport->port.membase + UCR1);
+	temp |= UCR1_TDMAEN;
+	writel(temp, sport->port.membase + UCR1);
+
+	/* fire it */
+	sport->dma_is_txing = 1;
+	dmaengine_submit(desc);
+	dma_async_issue_pending(chan);
+	return;
 }
 
 /*
@@ -596,14 +563,14 @@ static void imx_start_tx(struct uart_port *port)
 	unsigned long temp;
 
 	if (port->rs485.flags & SER_RS485_ENABLED) {
-		/* enable transmitter and shifter empty irq */
 		temp = readl(port->membase + UCR2);
 		if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
-			temp &= ~UCR2_CTS;
+			imx_port_rts_inactive(sport, &temp);
 		else
-			temp |= UCR2_CTS;
+			imx_port_rts_active(sport, &temp);
 		writel(temp, port->membase + UCR2);
 
+		/* enable transmitter and shifter empty irq */
 		temp = readl(port->membase + UCR4);
 		temp |= UCR4_TCEN;
 		writel(temp, port->membase + UCR4);
@@ -625,7 +592,9 @@ static void imx_start_tx(struct uart_port *port)
 			return;
 		}
 
-		schedule_delayed_work(&sport->tsk_dma_tx, 0);
+		if (!uart_circ_empty(&port->state->xmit) &&
+		    !uart_tx_stopped(port))
+			imx_dma_tx(sport);
 		return;
 	}
 }
@@ -718,7 +687,8 @@ static irqreturn_t imx_rxint(int irq, void *dev_id)
 		if (sport->port.ignore_status_mask & URXD_DUMMY_READ)
 			goto out;
 
-		tty_insert_flip_char(port, rx, flg);
+		if (tty_insert_flip_char(port, rx, flg) == 0)
+			sport->port.icount.buf_overrun++;
 	}
 
 out:
@@ -727,6 +697,38 @@ out:
 	return IRQ_HANDLED;
 }
 
+static int start_rx_dma(struct imx_port *sport);
+/*
+ * If the RXFIFO is filled with some data, and then we
+ * arise a DMA operation to receive them.
+ */
+static void imx_dma_rxint(struct imx_port *sport)
+{
+	unsigned long temp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+
+	temp = readl(sport->port.membase + USR2);
+	if ((temp & USR2_RDR) && !sport->dma_is_rxing) {
+		sport->dma_is_rxing = 1;
+
+		/* disable the receiver ready and aging timer interrupts */
+		temp = readl(sport->port.membase + UCR1);
+		temp &= ~(UCR1_RRDYEN);
+		writel(temp, sport->port.membase + UCR1);
+
+		temp = readl(sport->port.membase + UCR2);
+		temp &= ~(UCR2_ATEN);
+		writel(temp, sport->port.membase + UCR2);
+
+		/* tell the DMA to receive the data. */
+		start_rx_dma(sport);
+	}
+
+	spin_unlock_irqrestore(&sport->port.lock, flags);
+}
+
 static irqreturn_t imx_int(int irq, void *dev_id)
 {
 	struct imx_port *sport = dev_id;
@@ -736,11 +738,11 @@ static irqreturn_t imx_int(int irq, void *dev_id)
 	sts = readl(sport->port.membase + USR1);
 	sts2 = readl(sport->port.membase + USR2);
 
-	if ((sts & USR1_RRDY || sts & USR1_AGTIM) &&
-		!sport->dma_is_enabled) {
-		if (sts & USR1_AGTIM)
-			writel(USR1_AGTIM, sport->port.membase + USR1);
-		imx_rxint(irq, dev_id);
+	if (sts & (USR1_RRDY | USR1_AGTIM)) {
+		if (sport->dma_is_enabled)
+			imx_dma_rxint(sport);
+		else
+			imx_rxint(irq, dev_id);
 	}
 
 	if ((sts & USR1_TRDY &&
@@ -756,7 +758,6 @@ static irqreturn_t imx_int(int irq, void *dev_id)
 		writel(USR1_AWAKE, sport->port.membase + USR1);
 
 	if (sts2 & USR2_ORE) {
-		dev_err(sport->port.dev, "Rx FIFO overrun\n");
 		sport->port.icount.overrun++;
 		writel(USR2_ORE, sport->port.membase + USR2);
 	}
@@ -784,23 +785,35 @@ static unsigned int imx_tx_empty(struct uart_port *port)
 /*
  * We have a modem side uart, so the meanings of RTS and CTS are inverted.
  */
-static unsigned int imx_get_mctrl(struct uart_port *port)
+static unsigned int imx_get_hwmctrl(struct imx_port *sport)
 {
-	struct imx_port *sport = (struct imx_port *)port;
-	unsigned int tmp = TIOCM_DSR | TIOCM_CAR;
+	unsigned int tmp = TIOCM_DSR;
+	unsigned usr1 = readl(sport->port.membase + USR1);
 
-	if (readl(sport->port.membase + USR1) & USR1_RTSS)
+	if (usr1 & USR1_RTSS)
 		tmp |= TIOCM_CTS;
 
-	if (readl(sport->port.membase + UCR2) & UCR2_CTS)
-		tmp |= TIOCM_RTS;
+	/* in DCE mode DCDIN is always 0 */
+	if (!(usr1 & USR2_DCDIN))
+		tmp |= TIOCM_CAR;
 
-	if (readl(sport->port.membase + uts_reg(sport)) & UTS_LOOP)
-		tmp |= TIOCM_LOOP;
+	/* in DCE mode RIIN is always 0 */
+	if (readl(sport->port.membase + USR2) & USR2_RIIN)
+		tmp |= TIOCM_RI;
 
 	return tmp;
 }
 
+static unsigned int imx_get_mctrl(struct uart_port *port)
+{
+	struct imx_port *sport = (struct imx_port *)port;
+	unsigned int ret = imx_get_hwmctrl(sport);
+
+	mctrl_gpio_get(sport->gpios, &ret);
+
+	return ret;
+}
+
 static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 	struct imx_port *sport = (struct imx_port *)port;
@@ -814,10 +827,17 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 		writel(temp, sport->port.membase + UCR2);
 	}
 
+	temp = readl(sport->port.membase + UCR3) & ~UCR3_DSR;
+	if (!(mctrl & TIOCM_DTR))
+		temp |= UCR3_DSR;
+	writel(temp, sport->port.membase + UCR3);
+
 	temp = readl(sport->port.membase + uts_reg(sport)) & ~UTS_LOOP;
 	if (mctrl & TIOCM_LOOP)
 		temp |= UTS_LOOP;
 	writel(temp, sport->port.membase + uts_reg(sport));
+
+	mctrl_gpio_set(sport->gpios, mctrl);
 }
 
 /*
@@ -840,153 +860,183 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
-#define TXTL 2 /* reset default */
-#define RXTL 1 /* For console port */
-#define RXTL_UART 16 /* For uart */
-
-static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
+/*
+ * Handle any change of modem status signal since we were last called.
+ */
+static void imx_mctrl_check(struct imx_port *sport)
 {
-	unsigned int val;
-	unsigned int rx_fifo_trig;
+	unsigned int status, changed;
 
-	if (uart_console(&sport->port))
-		rx_fifo_trig = RXTL;
-	else
-		rx_fifo_trig = RXTL_UART;
+	status = imx_get_hwmctrl(sport);
+	changed = status ^ sport->old_status;
 
-	/* set receiver / transmitter trigger level */
-	val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
-	val |= TXTL << UFCR_TXTL_SHF | rx_fifo_trig;
-	writel(val, sport->port.membase + UFCR);
-	return 0;
-}
+	if (changed == 0)
+		return;
 
-#define RX_BUF_SIZE	(PAGE_SIZE)
-static void dma_rx_push_data(struct imx_port *sport, struct tty_struct *tty,
-				unsigned int start, unsigned int end)
-{
-	unsigned int i;
-	struct tty_port *port = &sport->port.state->port;
+	sport->old_status = status;
 
-	for (i = start; i < end; i++) {
-		if (sport->rx_buf.buf_info[i].filled) {
-			tty_insert_flip_string(port, sport->rx_buf.buf + (i
-					* RX_BUF_SIZE), sport->rx_buf.buf_info[i].rx_bytes);
-			tty_flip_buffer_push(port);
-			sport->rx_buf.buf_info[i].filled = false;
-			sport->rx_buf.last_completed_idx++;
-			sport->rx_buf.last_completed_idx %= IMX_RXBD_NUM;
-			sport->port.icount.rx += sport->rx_buf.buf_info[i].rx_bytes;
-		}
-	}
+	if (changed & TIOCM_RI)
+		sport->port.icount.rng++;
+	if (changed & TIOCM_DSR)
+		sport->port.icount.dsr++;
+	if (changed & TIOCM_CAR)
+		uart_handle_dcd_change(&sport->port, status & TIOCM_CAR);
+	if (changed & TIOCM_CTS)
+		uart_handle_cts_change(&sport->port, status & TIOCM_CTS);
+
+	wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
 }
 
-static void dma_rx_work(struct imx_port *sport)
+/*
+ * This is our per-port timeout handler, for checking the
+ * modem status signals.
+ */
+static void imx_timeout(unsigned long data)
 {
-	struct tty_struct *tty = sport->port.state->port.tty;
-	unsigned int cur_idx = sport->rx_buf.cur_idx;
+	struct imx_port *sport = (struct imx_port *)data;
+	unsigned long flags;
 
-	if (sport->rx_buf.last_completed_idx < cur_idx) {
-		dma_rx_push_data(sport, tty, sport->rx_buf.last_completed_idx + 1, cur_idx);
-	} else if (sport->rx_buf.last_completed_idx == (IMX_RXBD_NUM - 1)) {
-		dma_rx_push_data(sport, tty, 0, cur_idx);
-	} else {
-		dma_rx_push_data(sport, tty, sport->rx_buf.last_completed_idx + 1,
-					IMX_RXBD_NUM);
-		dma_rx_push_data(sport, tty, 0, cur_idx);
+	if (sport->port.state) {
+		spin_lock_irqsave(&sport->port.lock, flags);
+		imx_mctrl_check(sport);
+		spin_unlock_irqrestore(&sport->port.lock, flags);
+
+		mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
 	}
 }
 
+#define RX_BUF_SIZE	(PAGE_SIZE)
 static void imx_rx_dma_done(struct imx_port *sport)
 {
+	unsigned long temp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sport->port.lock, flags);
+
+	/* re-enable interrupts to get notified when new symbols are incoming */
+	temp = readl(sport->port.membase + UCR1);
+	temp |= UCR1_RRDYEN;
+	writel(temp, sport->port.membase + UCR1);
+
+	temp = readl(sport->port.membase + UCR2);
+	temp |= UCR2_ATEN;
+	writel(temp, sport->port.membase + UCR2);
+
 	sport->dma_is_rxing = 0;
 
 	/* Is the shutdown waiting for us? */
 	if (waitqueue_active(&sport->dma_wait))
 		wake_up(&sport->dma_wait);
+
+	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
 /*
- * There are three kinds of RX DMA interrupts(such as in the MX6Q):
+ * There are two kinds of RX DMA interrupts(such as in the MX6Q):
  *   [1] the RX DMA buffer is full.
- *   [2] the Aging timer expires(wait for 8 bytes long)
- *   [3] the Idle Condition Detect(enabled the UCR4_IDDMAEN).
+ *   [2] the aging timer expires
  *
- * The [2] is trigger when a character was been sitting in the FIFO
- * meanwhile [3] can wait for 32 bytes long when the RX line is
- * on IDLE state and RxFIFO is empty.
+ * Condition [2] is triggered when a character has been sitting in the FIFO
+ * for at least 8 byte durations.
  */
 static void dma_rx_callback(void *data)
 {
 	struct imx_port *sport = data;
 	struct dma_chan	*chan = sport->dma_chan_rx;
-	struct tty_struct *tty = sport->port.state->port.tty;
+	struct scatterlist *sgl = &sport->rx_sgl;
+	struct tty_port *port = &sport->port.state->port;
 	struct dma_tx_state state;
 	enum dma_status status;
 	unsigned int count;
 
-	/* If we have finish the reading. we will not accept any more data. */
-	if (tty->closing) {
-		imx_rx_dma_done(sport);
-		return;
-	}
+	/* unmap it first */
+	dma_unmap_sg(sport->port.dev, sgl, 1, DMA_FROM_DEVICE);
 
-	status = dmaengine_tx_status(chan, sport->rx_buf.cookie, &state);
+	status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
 	count = RX_BUF_SIZE - state.residue;
-	sport->rx_buf.buf_info[sport->rx_buf.cur_idx].filled = true;
-	sport->rx_buf.buf_info[sport->rx_buf.cur_idx].rx_bytes = count;
-	sport->rx_buf.cur_idx++;
-	sport->rx_buf.cur_idx %= IMX_RXBD_NUM;
+
 	dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
 
-	if (sport->rx_buf.cur_idx == sport->rx_buf.last_completed_idx)
-		dev_err(sport->port.dev, "overwrite!\n");
+	if (count) {
+		if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) {
+			int bytes = tty_insert_flip_string(port, sport->rx_buf,
+					count);
 
-	if (count)
-		dma_rx_work(sport);
+			if (bytes != count)
+				sport->port.icount.buf_overrun++;
+		}
+		tty_flip_buffer_push(port);
+		sport->port.icount.rx += count;
+	}
+
+	/*
+	 * Restart RX DMA directly if more data is available in order to skip
+	 * the roundtrip through the IRQ handler. If there is some data already
+	 * in the FIFO, DMA needs to be restarted soon anyways.
+	 *
+	 * Otherwise stop the DMA and reactivate FIFO IRQs to restart DMA once
+	 * data starts to arrive again.
+	 */
+	if (readl(sport->port.membase + USR2) & USR2_RDR)
+		start_rx_dma(sport);
+	else
+		imx_rx_dma_done(sport);
 }
 
 static int start_rx_dma(struct imx_port *sport)
 {
+	struct scatterlist *sgl = &sport->rx_sgl;
 	struct dma_chan	*chan = sport->dma_chan_rx;
+	struct device *dev = sport->port.dev;
 	struct dma_async_tx_descriptor *desc;
+	int ret;
 
-	sport->rx_buf.periods = IMX_RXBD_NUM;
-	sport->rx_buf.period_len = RX_BUF_SIZE;
-	sport->rx_buf.buf_len = IMX_RXBD_NUM * RX_BUF_SIZE;
-	sport->rx_buf.cur_idx = 0;
-	sport->rx_buf.last_completed_idx = -1;
-	desc = dmaengine_prep_dma_cyclic(chan, sport->rx_buf.dmaaddr,
-		sport->rx_buf.buf_len, sport->rx_buf.period_len,
-		DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
+	sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE);
+	ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE);
+	if (ret == 0) {
+		dev_err(dev, "DMA mapping error for RX.\n");
+		return -EINVAL;
+	}
+	desc = dmaengine_prep_slave_sg(chan, sgl, 1, DMA_DEV_TO_MEM,
+					DMA_PREP_INTERRUPT);
 	if (!desc) {
-		dev_err(sport->port.dev, "Prepare for the RX slave dma failed!\n");
+		dma_unmap_sg(dev, sgl, 1, DMA_FROM_DEVICE);
+		dev_err(dev, "We cannot prepare for the RX slave dma!\n");
 		return -EINVAL;
 	}
-
 	desc->callback = dma_rx_callback;
 	desc->callback_param = sport;
 
-	dev_dbg(sport->port.dev, "RX: prepare for the DMA.\n");
-	sport->rx_buf.cookie = dmaengine_submit(desc);
+	dev_dbg(dev, "RX: prepare for the DMA.\n");
+	dmaengine_submit(desc);
 	dma_async_issue_pending(chan);
-
-	sport->dma_is_rxing = 1;
 	return 0;
 }
 
+#define TXTL_DEFAULT 2 /* reset default */
+#define RXTL_DEFAULT 1 /* reset default */
+#define TXTL_DMA 8 /* DMA burst setting */
+#define RXTL_DMA 9 /* DMA burst setting */
+
+static void imx_setup_ufcr(struct imx_port *sport,
+			  unsigned char txwl, unsigned char rxwl)
+{
+	unsigned int val;
+
+	/* set receiver / transmitter trigger level */
+	val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
+	val |= txwl << UFCR_TXTL_SHF | rxwl;
+	writel(val, sport->port.membase + UFCR);
+}
+
 static void imx_uart_dma_exit(struct imx_port *sport)
 {
 	if (sport->dma_chan_rx) {
 		dma_release_channel(sport->dma_chan_rx);
 		sport->dma_chan_rx = NULL;
 
-		if (sport->rx_buf.buf) {
-			dma_free_coherent(NULL, IMX_RXBD_NUM * RX_BUF_SIZE,
-						(void *)sport->rx_buf.buf,
-						sport->rx_buf.dmaaddr);
-			sport->rx_buf.buf = NULL;
-		}
+		kfree(sport->rx_buf);
+		sport->rx_buf = NULL;
 	}
 
 	if (sport->dma_chan_tx) {
@@ -1001,7 +1051,7 @@ static int imx_uart_dma_init(struct imx_port *sport)
 {
 	struct dma_slave_config slave_config = {};
 	struct device *dev = sport->port.dev;
-	int ret, i;
+	int ret;
 
 	/* Prepare for RX : */
 	sport->dma_chan_rx = dma_request_slave_channel(dev, "rx");
@@ -1014,26 +1064,20 @@ static int imx_uart_dma_init(struct imx_port *sport)
 	slave_config.direction = DMA_DEV_TO_MEM;
 	slave_config.src_addr = sport->port.mapbase + URXD0;
 	slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-	slave_config.src_maxburst = RXTL_UART;
+	/* one byte less than the watermark level to enable the aging timer */
+	slave_config.src_maxburst = RXTL_DMA - 1;
 	ret = dmaengine_slave_config(sport->dma_chan_rx, &slave_config);
 	if (ret) {
 		dev_err(dev, "error in RX dma configuration.\n");
 		goto err;
 	}
 
-	sport->rx_buf.buf = dma_alloc_coherent(NULL, IMX_RXBD_NUM * RX_BUF_SIZE,
-					&sport->rx_buf.dmaaddr, GFP_KERNEL);
-	if (!sport->rx_buf.buf) {
-		dev_err(dev, "cannot alloc DMA buffer.\n");
+	sport->rx_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!sport->rx_buf) {
 		ret = -ENOMEM;
 		goto err;
 	}
 
-	for (i = 0; i < IMX_RXBD_NUM; i++) {
-		sport->rx_buf.buf_info[i].rx_bytes = 0;
-		sport->rx_buf.buf_info[i].filled = false;
-	}
-
 	/* Prepare for TX : */
 	sport->dma_chan_tx = dma_request_slave_channel(dev, "tx");
 	if (!sport->dma_chan_tx) {
@@ -1045,7 +1089,7 @@ static int imx_uart_dma_init(struct imx_port *sport)
 	slave_config.direction = DMA_MEM_TO_DEV;
 	slave_config.dst_addr = sport->port.mapbase + URTX0;
 	slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-	slave_config.dst_maxburst = TXTL;
+	slave_config.dst_maxburst = TXTL_DMA;
 	ret = dmaengine_slave_config(sport->dma_chan_tx, &slave_config);
 	if (ret) {
 		dev_err(dev, "error in TX dma configuration.");
@@ -1065,19 +1109,17 @@ static void imx_enable_dma(struct imx_port *sport)
 	unsigned long temp;
 
 	init_waitqueue_head(&sport->dma_wait);
-	sport->flags = 0;
 
 	/* set UCR1 */
 	temp = readl(sport->port.membase + UCR1);
-	temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN |
-		/* wait for 32 idle frames for IDDMA interrupt */
-		UCR1_ICD_REG(3);
+	temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN;
 	writel(temp, sport->port.membase + UCR1);
 
-	/* set UCR4 */
-	temp = readl(sport->port.membase + UCR4);
-	temp |= UCR4_IDDMAEN;
-	writel(temp, sport->port.membase + UCR4);
+	temp = readl(sport->port.membase + UCR2);
+	temp |= UCR2_ATEN;
+	writel(temp, sport->port.membase + UCR2);
+
+	imx_setup_ufcr(sport, TXTL_DMA, RXTL_DMA);
 
 	sport->dma_is_enabled = 1;
 }
@@ -1093,13 +1135,10 @@ static void imx_disable_dma(struct imx_port *sport)
 
 	/* clear UCR2 */
 	temp = readl(sport->port.membase + UCR2);
-	temp &= ~(UCR2_CTSC | UCR2_CTS);
+	temp &= ~(UCR2_CTSC | UCR2_CTS | UCR2_ATEN);
 	writel(temp, sport->port.membase + UCR2);
 
-	/* clear UCR4 */
-	temp = readl(sport->port.membase + UCR4);
-	temp &= ~UCR4_IDDMAEN;
-	writel(temp, sport->port.membase + UCR4);
+	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 	sport->dma_is_enabled = 0;
 }
@@ -1122,7 +1161,7 @@ static int imx_startup(struct uart_port *port)
 		return retval;
 	}
 
-	imx_setup_ufcr(sport, 0);
+	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 	/* disable the DREN bit (Data Ready interrupt enable) before
 	 * requesting IRQs
@@ -1135,6 +1174,12 @@ static int imx_startup(struct uart_port *port)
 
 	writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
 
+	/* Can we enable the DMA support? */
+	if (is_imx6q_uart(sport) && !uart_console(port) &&
+	    !sport->dma_is_inited)
+		imx_uart_dma_init(sport);
+
+	spin_lock_irqsave(&sport->port.lock, flags);
 	/* Reset fifo's and state machines */
 	i = 100;
 
@@ -1145,28 +1190,18 @@ static int imx_startup(struct uart_port *port)
 	while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0))
 		udelay(1);
 
-	/* Can we enable the DMA support? */
-	if (is_imx6q_uart(sport) && !uart_console(port)
-		&& !sport->dma_is_inited)
-		imx_uart_dma_init(sport);
-
-	if (sport->dma_is_inited)
-		INIT_DELAYED_WORK(&sport->tsk_dma_tx, dma_tx_work);
-
-	spin_lock_irqsave(&sport->port.lock, flags);
-
 	/*
 	 * Finally, clear and enable interrupts
 	 */
 	writel(USR1_RTSD, sport->port.membase + USR1);
 	writel(USR2_ORE, sport->port.membase + USR2);
 
+	if (sport->dma_is_inited && !sport->dma_is_enabled)
+		imx_enable_dma(sport);
+
 	temp = readl(sport->port.membase + UCR1);
-	if (!sport->dma_is_inited)
-		temp |= UCR1_RRDYEN;
-	if (sport->have_rtscts)
-		temp |= UCR1_RTSDEN;
-	temp |= UCR1_UARTEN;
+	temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
+
 	writel(temp, sport->port.membase + UCR1);
 
 	temp = readl(sport->port.membase + UCR4);
@@ -1204,18 +1239,14 @@ static void imx_shutdown(struct uart_port *port)
 		int ret;
 
 		/* We have to wait for the DMA to finish. */
-		ret = wait_event_interruptible_timeout(sport->dma_wait,
-			!sport->dma_is_rxing && !sport->dma_is_txing,
-			msecs_to_jiffies(1));
-		if (ret <= 0) {
+		ret = wait_event_interruptible(sport->dma_wait,
+			!sport->dma_is_rxing && !sport->dma_is_txing);
+		if (ret != 0) {
 			sport->dma_is_rxing = 0;
 			sport->dma_is_txing = 0;
 			dmaengine_terminate_all(sport->dma_chan_tx);
 			dmaengine_terminate_all(sport->dma_chan_rx);
 		}
-
-		cancel_delayed_work_sync(&sport->tsk_dma_tx);
-
 		spin_lock_irqsave(&sport->port.lock, flags);
 		imx_stop_tx(port);
 		imx_stop_rx(port);
@@ -1224,6 +1255,8 @@ static void imx_shutdown(struct uart_port *port)
 		imx_uart_dma_exit(sport);
 	}
 
+	mctrl_gpio_disable_ms(sport->gpios);
+
 	spin_lock_irqsave(&sport->port.lock, flags);
 	temp = readl(sport->port.membase + UCR2);
 	temp &= ~(UCR2_TXEN);
@@ -1301,9 +1334,10 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 {
 	struct imx_port *sport = (struct imx_port *)port;
 	unsigned long flags;
-	unsigned int ucr2, old_ucr1, old_txrxen, baud, quot;
+	unsigned long ucr2, old_ucr1, old_ucr2;
+	unsigned int baud, quot;
 	unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8;
-	unsigned int div, ufcr;
+	unsigned long div, ufcr;
 	unsigned long num, denom;
 	uint64_t tdiv64;
 
@@ -1332,19 +1366,25 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 				 * it under manual control and keep transmitter
 				 * disabled.
 				 */
-				if (!(port->rs485.flags &
-				      SER_RS485_RTS_AFTER_SEND))
-					ucr2 |= UCR2_CTS;
+				if (port->rs485.flags &
+				    SER_RS485_RTS_AFTER_SEND)
+					imx_port_rts_inactive(sport, &ucr2);
+				else
+					imx_port_rts_active(sport, &ucr2);
 			} else {
-				ucr2 |= UCR2_CTSC;
+				imx_port_rts_auto(sport, &ucr2);
 			}
 		} else {
 			termios->c_cflag &= ~CRTSCTS;
 		}
-	} else if (port->rs485.flags & SER_RS485_ENABLED)
+	} else if (port->rs485.flags & SER_RS485_ENABLED) {
 		/* disable transmitter */
-		if (!(port->rs485.flags & SER_RS485_RTS_AFTER_SEND))
-			ucr2 |= UCR2_CTS;
+		if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+			imx_port_rts_inactive(sport, &ucr2);
+		else
+			imx_port_rts_active(sport, &ucr2);
+	}
+
 
 	if (termios->c_cflag & CSTOPB)
 		ucr2 |= UCR2_STPB;
@@ -1405,10 +1445,10 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 		barrier();
 
 	/* then, disable everything */
-	old_txrxen = readl(sport->port.membase + UCR2);
-	writel(old_txrxen & ~(UCR2_TXEN | UCR2_RXEN),
+	old_ucr2 = readl(sport->port.membase + UCR2);
+	writel(old_ucr2 & ~(UCR2_TXEN | UCR2_RXEN),
 			sport->port.membase + UCR2);
-	old_txrxen &= (UCR2_TXEN | UCR2_RXEN);
+	old_ucr2 &= (UCR2_TXEN | UCR2_RXEN | UCR2_ATEN);
 
 	/* custom-baudrate handling */
 	div = sport->port.uartclk / (baud * 16);
@@ -1449,21 +1489,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 	writel(old_ucr1, sport->port.membase + UCR1);
 
 	/* set the parity, stop bits and data size */
-	writel(ucr2 | old_txrxen, sport->port.membase + UCR2);
+	writel(ucr2 | old_ucr2, sport->port.membase + UCR2);
 
 	if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
 		imx_enable_ms(&sport->port);
 
-	if (sport->dma_is_inited && !sport->dma_is_enabled) {
-		imx_enable_dma(sport);
-		start_rx_dma(sport);
-	}
-
-	if (!sport->dma_is_enabled) {
-		ucr2 = readl(sport->port.membase + UCR2);
-		writel(ucr2 | UCR2_ATEN, sport->port.membase + UCR2);
-	}
-
 	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
@@ -1529,7 +1559,7 @@ static int imx_poll_init(struct uart_port *port)
 	if (retval)
 		clk_disable_unprepare(sport->clk_ipg);
 
-	imx_setup_ufcr(sport, 0);
+	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 
@@ -1595,11 +1625,10 @@ static int imx_rs485_config(struct uart_port *port,
 
 		/* disable transmitter */
 		temp = readl(sport->port.membase + UCR2);
-		temp &= ~UCR2_CTSC;
 		if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
-			temp &= ~UCR2_CTS;
+			imx_port_rts_inactive(sport, &temp);
 		else
-			temp |= UCR2_CTS;
+			imx_port_rts_active(sport, &temp);
 		writel(temp, sport->port.membase + UCR2);
 	}
 
@@ -1799,7 +1828,7 @@ imx_console_setup(struct console *co, char *options)
 	else
 		imx_console_get_options(sport, &baud, &parity, &bits);
 
-	imx_setup_ufcr(sport, 0);
+	imx_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
 
 	retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
 
@@ -1829,6 +1858,38 @@ static struct console imx_console = {
 };
 
 #define IMX_CONSOLE	&imx_console
+
+#ifdef CONFIG_OF
+static void imx_console_early_putchar(struct uart_port *port, int ch)
+{
+	while (readl_relaxed(port->membase + IMX21_UTS) & UTS_TXFULL)
+		cpu_relax();
+
+	writel_relaxed(ch, port->membase + URTX0);
+}
+
+static void imx_console_early_write(struct console *con, const char *s,
+				    unsigned count)
+{
+	struct earlycon_device *dev = con->data;
+
+	uart_console_write(&dev->port, s, count, imx_console_early_putchar);
+}
+
+static int __init
+imx_console_early_setup(struct earlycon_device *dev, const char *opt)
+{
+	if (!dev->port.membase)
+		return -ENODEV;
+
+	dev->con->write = imx_console_early_write;
+
+	return 0;
+}
+OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup);
+OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
+#endif
+
 #else
 #define IMX_CONSOLE	NULL
 #endif
@@ -1843,72 +1904,6 @@ static struct uart_driver imx_reg = {
 	.cons           = IMX_CONSOLE,
 };
 
-static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct imx_port *sport = platform_get_drvdata(dev);
-	unsigned int val;
-
-	/* enable wakeup from i.MX UART */
-	val = readl(sport->port.membase + UCR3);
-	val |= UCR3_AWAKEN;
-	writel(val, sport->port.membase + UCR3);
-
-	uart_suspend_port(&imx_reg, &sport->port);
-	disable_irq(sport->port.irq);
-
-	/* Save necessary regs */
-	clk_prepare_enable(sport->clk_ipg);
-	sport->saved_reg[0] = readl(sport->port.membase + UCR1);
-	sport->saved_reg[1] = readl(sport->port.membase + UCR2);
-	sport->saved_reg[2] = readl(sport->port.membase + UCR3);
-	sport->saved_reg[3] = readl(sport->port.membase + UCR4);
-	sport->saved_reg[4] = readl(sport->port.membase + UFCR);
-	sport->saved_reg[5] = readl(sport->port.membase + UESC);
-	sport->saved_reg[6] = readl(sport->port.membase + UTIM);
-	sport->saved_reg[7] = readl(sport->port.membase + UBIR);
-	sport->saved_reg[8] = readl(sport->port.membase + UBMR);
-	sport->saved_reg[9] = readl(sport->port.membase + IMX21_UTS);
-	clk_disable_unprepare(sport->clk_ipg);
-
-	pinctrl_pm_select_sleep_state(&dev->dev);
-
-	return 0;
-}
-
-static int serial_imx_resume(struct platform_device *dev)
-{
-	struct imx_port *sport = platform_get_drvdata(dev);
-	unsigned int val;
-
-	pinctrl_pm_select_default_state(&dev->dev);
-
-	clk_prepare_enable(sport->clk_ipg);
-	writel(sport->saved_reg[4], sport->port.membase + UFCR);
-	writel(sport->saved_reg[5], sport->port.membase + UESC);
-	writel(sport->saved_reg[6], sport->port.membase + UTIM);
-	writel(sport->saved_reg[7], sport->port.membase + UBIR);
-	writel(sport->saved_reg[8], sport->port.membase + UBMR);
-	writel(sport->saved_reg[9], sport->port.membase + IMX21_UTS);
-	writel(sport->saved_reg[0], sport->port.membase + UCR1);
-	writel(sport->saved_reg[1] | 0x1, sport->port.membase + UCR2);
-	writel(sport->saved_reg[2], sport->port.membase + UCR3);
-	writel(sport->saved_reg[3], sport->port.membase + UCR4);
-
-	/* disable wakeup from i.MX UART */
-	val = readl(sport->port.membase + UCR3);
-	val &= ~UCR3_AWAKEN;
-	writel(val, sport->port.membase + UCR3);
-	val = readl(sport->port.membase + USR1);
-	if (val & USR1_AWAKE)
-		writel(USR1_AWAKE, sport->port.membase + USR1);
-	clk_disable_unprepare(sport->clk_ipg);
-
-	uart_resume_port(&imx_reg, &sport->port);
-	enable_irq(sport->port.irq);
-
-	return 0;
-}
-
 #ifdef CONFIG_OF
 /*
  * This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it
@@ -1918,11 +1913,10 @@ static int serial_imx_probe_dt(struct imx_port *sport,
 		struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-	const struct of_device_id *of_id =
-			of_match_device(imx_uart_dt_ids, &pdev->dev);
 	int ret;
 
-	if (!np)
+	sport->devdata = of_device_get_match_data(&pdev->dev);
+	if (!sport->devdata)
 		/* no device tree device */
 		return 1;
 
@@ -1939,8 +1933,6 @@ static int serial_imx_probe_dt(struct imx_port *sport,
 	if (of_get_property(np, "fsl,dte-mode", NULL))
 		sport->dte_mode = 1;
 
-	sport->devdata = of_id->data;
-
 	return 0;
 }
 #else
@@ -1970,7 +1962,7 @@ static int serial_imx_probe(struct platform_device *pdev)
 {
 	struct imx_port *sport;
 	void __iomem *base;
-	int ret = 0;
+	int ret = 0, reg;
 	struct resource *res;
 	int txirq, rxirq, rtsirq;
 
@@ -2009,6 +2001,10 @@ static int serial_imx_probe(struct platform_device *pdev)
 	sport->timer.function = imx_timeout;
 	sport->timer.data     = (unsigned long)sport;
 
+	sport->gpios = mctrl_gpio_init(&sport->port, 0);
+	if (IS_ERR(sport->gpios))
+		return PTR_ERR(sport->gpios);
+
 	sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
 	if (IS_ERR(sport->clk_ipg)) {
 		ret = PTR_ERR(sport->clk_ipg);
@@ -2024,14 +2020,19 @@ static int serial_imx_probe(struct platform_device *pdev)
 	}
 
 	sport->port.uartclk = clk_get_rate(sport->clk_per);
-	if (sport->port.uartclk > IMX_MODULE_MAX_CLK_RATE) {
-		ret = clk_set_rate(sport->clk_per, IMX_MODULE_MAX_CLK_RATE);
-		if (ret < 0) {
-			dev_err(&pdev->dev, "clk_set_rate() failed\n");
-			return ret;
-		}
-	}
-	sport->port.uartclk = clk_get_rate(sport->clk_per);
+
+	/* For register access, we only need to enable the ipg clock. */
+	ret = clk_prepare_enable(sport->clk_ipg);
+	if (ret)
+		return ret;
+
+	/* Disable interrupts before requesting them */
+	reg = readl_relaxed(sport->port.membase + UCR1);
+	reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN |
+		 UCR1_TXMPTYEN | UCR1_RTSDEN);
+	writel_relaxed(reg, sport->port.membase + UCR1);
+
+	clk_disable_unprepare(sport->clk_ipg);
 
 	/*
 	 * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
@@ -2068,16 +2069,138 @@ static int serial_imx_remove(struct platform_device *pdev)
 	return uart_remove_one_port(&imx_reg, &sport->port);
 }
 
+static void serial_imx_restore_context(struct imx_port *sport)
+{
+	if (!sport->context_saved)
+		return;
+
+	writel(sport->saved_reg[4], sport->port.membase + UFCR);
+	writel(sport->saved_reg[5], sport->port.membase + UESC);
+	writel(sport->saved_reg[6], sport->port.membase + UTIM);
+	writel(sport->saved_reg[7], sport->port.membase + UBIR);
+	writel(sport->saved_reg[8], sport->port.membase + UBMR);
+	writel(sport->saved_reg[9], sport->port.membase + IMX21_UTS);
+	writel(sport->saved_reg[0], sport->port.membase + UCR1);
+	writel(sport->saved_reg[1] | UCR2_SRST, sport->port.membase + UCR2);
+	writel(sport->saved_reg[2], sport->port.membase + UCR3);
+	writel(sport->saved_reg[3], sport->port.membase + UCR4);
+	sport->context_saved = false;
+}
+
+static void serial_imx_save_context(struct imx_port *sport)
+{
+	/* Save necessary regs */
+	sport->saved_reg[0] = readl(sport->port.membase + UCR1);
+	sport->saved_reg[1] = readl(sport->port.membase + UCR2);
+	sport->saved_reg[2] = readl(sport->port.membase + UCR3);
+	sport->saved_reg[3] = readl(sport->port.membase + UCR4);
+	sport->saved_reg[4] = readl(sport->port.membase + UFCR);
+	sport->saved_reg[5] = readl(sport->port.membase + UESC);
+	sport->saved_reg[6] = readl(sport->port.membase + UTIM);
+	sport->saved_reg[7] = readl(sport->port.membase + UBIR);
+	sport->saved_reg[8] = readl(sport->port.membase + UBMR);
+	sport->saved_reg[9] = readl(sport->port.membase + IMX21_UTS);
+	sport->context_saved = true;
+}
+
+static void serial_imx_enable_wakeup(struct imx_port *sport, bool on)
+{
+	unsigned int val;
+
+	val = readl(sport->port.membase + UCR3);
+	if (on)
+		val |= UCR3_AWAKEN;
+	else
+		val &= ~UCR3_AWAKEN;
+	writel(val, sport->port.membase + UCR3);
+
+	val = readl(sport->port.membase + UCR1);
+	if (on)
+		val |= UCR1_RTSDEN;
+	else
+		val &= ~UCR1_RTSDEN;
+	writel(val, sport->port.membase + UCR1);
+}
+
+static int imx_serial_port_suspend_noirq(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct imx_port *sport = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = clk_enable(sport->clk_ipg);
+	if (ret)
+		return ret;
+
+	serial_imx_save_context(sport);
+
+	clk_disable(sport->clk_ipg);
+
+	return 0;
+}
+
+static int imx_serial_port_resume_noirq(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct imx_port *sport = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = clk_enable(sport->clk_ipg);
+	if (ret)
+		return ret;
+
+	serial_imx_restore_context(sport);
+
+	clk_disable(sport->clk_ipg);
+
+	return 0;
+}
+
+static int imx_serial_port_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct imx_port *sport = platform_get_drvdata(pdev);
+
+	/* enable wakeup from i.MX UART */
+	serial_imx_enable_wakeup(sport, true);
+
+	uart_suspend_port(&imx_reg, &sport->port);
+
+	/* Needed to enable clock in suspend_noirq */
+	return clk_prepare(sport->clk_ipg);
+}
+
+static int imx_serial_port_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct imx_port *sport = platform_get_drvdata(pdev);
+
+	/* disable wakeup from i.MX UART */
+	serial_imx_enable_wakeup(sport, false);
+
+	uart_resume_port(&imx_reg, &sport->port);
+
+	clk_unprepare(sport->clk_ipg);
+
+	return 0;
+}
+
+static const struct dev_pm_ops imx_serial_port_pm_ops = {
+	.suspend_noirq = imx_serial_port_suspend_noirq,
+	.resume_noirq = imx_serial_port_resume_noirq,
+	.suspend = imx_serial_port_suspend,
+	.resume = imx_serial_port_resume,
+};
+
 static struct platform_driver serial_imx_driver = {
 	.probe		= serial_imx_probe,
 	.remove		= serial_imx_remove,
 
-	.suspend	= serial_imx_suspend,
-	.resume		= serial_imx_resume,
 	.id_table	= imx_uart_devtype,
 	.driver		= {
 		.name	= "imx-uart",
 		.of_match_table = imx_uart_dt_ids,
+		.pm	= &imx_serial_port_pm_ops,
 	},
 };
 
diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c
index 0ec756c..b93fd2d 100644
--- a/drivers/tty/serial/serial_mctrl_gpio.c
+++ b/drivers/tty/serial/serial_mctrl_gpio.c
@@ -12,18 +12,23 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
  */
 
 #include <linux/err.h>
 #include <linux/device.h>
+#include <linux/irq.h>
 #include <linux/gpio/consumer.h>
 #include <linux/termios.h>
+#include <linux/serial_core.h>
 
 #include "serial_mctrl_gpio.h"
 
 struct mctrl_gpios {
+	struct uart_port *port;
 	struct gpio_desc *gpio[UART_GPIO_MAX];
+	int irq[UART_GPIO_MAX];
+	unsigned int mctrl_prev;
+	bool mctrl_on;
 };
 
 static const struct {
@@ -49,8 +54,7 @@ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsigned int mctrl)
 	unsigned int count = 0;
 
 	for (i = 0; i < UART_GPIO_MAX; i++)
-		if (!IS_ERR_OR_NULL(gpios->gpio[i]) &&
-		    mctrl_gpios_desc[i].dir_out) {
+		if (gpios->gpio[i] && mctrl_gpios_desc[i].dir_out) {
 			desc_array[count] = gpios->gpio[i];
 			value_array[count] = !!(mctrl & mctrl_gpios_desc[i].mctrl);
 			count++;
@@ -83,7 +87,7 @@ unsigned int mctrl_gpio_get(struct mctrl_gpios *gpios, unsigned int *mctrl)
 }
 EXPORT_SYMBOL_GPL(mctrl_gpio_get);
 
-struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
+struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
 {
 	struct mctrl_gpios *gpios;
 	enum mctrl_gpio_idx i;
@@ -111,15 +115,137 @@ struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
 
 	return gpios;
 }
+EXPORT_SYMBOL_GPL(mctrl_gpio_init_noauto);
+
+#define MCTRL_ANY_DELTA (TIOCM_RI | TIOCM_DSR | TIOCM_CD | TIOCM_CTS)
+static irqreturn_t mctrl_gpio_irq_handle(int irq, void *context)
+{
+	struct mctrl_gpios *gpios = context;
+	struct uart_port *port = gpios->port;
+	u32 mctrl = gpios->mctrl_prev;
+	u32 mctrl_diff;
+
+	mctrl_gpio_get(gpios, &mctrl);
+
+	mctrl_diff = mctrl ^ gpios->mctrl_prev;
+	gpios->mctrl_prev = mctrl;
+
+	if (mctrl_diff & MCTRL_ANY_DELTA && port->state != NULL) {
+		if ((mctrl_diff & mctrl) & TIOCM_RI)
+			port->icount.rng++;
+
+		if ((mctrl_diff & mctrl) & TIOCM_DSR)
+			port->icount.dsr++;
+
+		if (mctrl_diff & TIOCM_CD)
+			uart_handle_dcd_change(port, mctrl & TIOCM_CD);
+
+		if (mctrl_diff & TIOCM_CTS)
+			uart_handle_cts_change(port, mctrl & TIOCM_CTS);
+
+		wake_up_interruptible(&port->state->port.delta_msr_wait);
+	}
+
+	return IRQ_HANDLED;
+}
+
+struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx)
+{
+	struct mctrl_gpios *gpios;
+	enum mctrl_gpio_idx i;
+
+	gpios = mctrl_gpio_init_noauto(port->dev, idx);
+	if (IS_ERR(gpios))
+		return gpios;
+
+	gpios->port = port;
+
+	for (i = 0; i < UART_GPIO_MAX; ++i) {
+		int ret;
+
+		if (!gpios->gpio[i] || mctrl_gpios_desc[i].dir_out)
+			continue;
+
+		ret = gpiod_to_irq(gpios->gpio[i]);
+		if (ret <= 0) {
+			dev_err(port->dev,
+				"failed to find corresponding irq for %s (idx=%d, err=%d)\n",
+				mctrl_gpios_desc[i].name, idx, ret);
+			return ERR_PTR(ret);
+		}
+		gpios->irq[i] = ret;
+
+		/* irqs should only be enabled in .enable_ms */
+		irq_set_status_flags(gpios->irq[i], IRQ_NOAUTOEN);
+
+		ret = devm_request_irq(port->dev, gpios->irq[i],
+				       mctrl_gpio_irq_handle,
+				       IRQ_TYPE_EDGE_BOTH, dev_name(port->dev),
+				       gpios);
+		if (ret) {
+			/* alternatively implement polling */
+			dev_err(port->dev,
+				"failed to request irq for %s (idx=%d, err=%d)\n",
+				mctrl_gpios_desc[i].name, idx, ret);
+			return ERR_PTR(ret);
+		}
+	}
+
+	return gpios;
+}
 EXPORT_SYMBOL_GPL(mctrl_gpio_init);
 
 void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
 {
 	enum mctrl_gpio_idx i;
 
-	for (i = 0; i < UART_GPIO_MAX; i++)
-		if (!IS_ERR_OR_NULL(gpios->gpio[i]))
+	for (i = 0; i < UART_GPIO_MAX; i++) {
+		if (gpios->irq[i])
+			devm_free_irq(gpios->port->dev, gpios->irq[i], gpios);
+
+		if (gpios->gpio[i])
 			devm_gpiod_put(dev, gpios->gpio[i]);
+	}
 	devm_kfree(dev, gpios);
 }
 EXPORT_SYMBOL_GPL(mctrl_gpio_free);
+
+void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
+{
+	enum mctrl_gpio_idx i;
+
+	/* .enable_ms may be called multiple times */
+	if (gpios->mctrl_on)
+		return;
+
+	gpios->mctrl_on = true;
+
+	/* get initial status of modem lines GPIOs */
+	mctrl_gpio_get(gpios, &gpios->mctrl_prev);
+
+	for (i = 0; i < UART_GPIO_MAX; ++i) {
+		if (!gpios->irq[i])
+			continue;
+
+		enable_irq(gpios->irq[i]);
+	}
+}
+EXPORT_SYMBOL_GPL(mctrl_gpio_enable_ms);
+
+void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
+{
+	enum mctrl_gpio_idx i;
+
+	if (!gpios->mctrl_on)
+		return;
+
+	gpios->mctrl_on = false;
+
+	for (i = 0; i < UART_GPIO_MAX; ++i) {
+		if (!gpios->irq[i])
+			continue;
+
+		disable_irq(gpios->irq[i]);
+	}
+}
+EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms);
diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h
index 400ba04..9716db2 100644
--- a/drivers/tty/serial/serial_mctrl_gpio.h
+++ b/drivers/tty/serial/serial_mctrl_gpio.h
@@ -22,6 +22,8 @@
 #include <linux/device.h>
 #include <linux/gpio/consumer.h>
 
+struct uart_port;
+
 enum mctrl_gpio_idx {
 	UART_GPIO_CTS,
 	UART_GPIO_DSR,
@@ -60,12 +62,22 @@ struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
 				      enum mctrl_gpio_idx gidx);
 
 /*
+ * Request and set direction of modem control lines GPIOs and sets up irq
+ * handling.
+ * devm_* functions are used, so there's no need to call mctrl_gpio_free().
+ * Returns a pointer to the allocated mctrl structure if ok, -ENOMEM on
+ * allocation error.
+ */
+struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx);
+
+/*
  * Request and set direction of modem control lines GPIOs.
  * devm_* functions are used, so there's no need to call mctrl_gpio_free().
  * Returns a pointer to the allocated mctrl structure if ok, -ENOMEM on
  * allocation error.
  */
-struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx);
+struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev,
+					   unsigned int idx);
 
 /*
  * Free the mctrl_gpios structure.
@@ -74,6 +86,16 @@ struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx);
  */
 void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios);
 
+/*
+ * Enable gpio interrupts to report status line changes.
+ */
+void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios);
+
+/*
+ * Disable gpio interrupts to report status line changes.
+ */
+void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios);
+
 #else /* GPIOLIB */
 
 static inline
@@ -95,7 +117,13 @@ struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios,
 }
 
 static inline
-struct mctrl_gpios *mctrl_gpio_init(struct device *dev, unsigned int idx)
+struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsigned int idx)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline
+struct mctrl_gpios *mctrl_gpio_init_noauto(struct device *dev, unsigned int idx)
 {
 	return ERR_PTR(-ENOSYS);
 }
@@ -105,6 +133,14 @@ void mctrl_gpio_free(struct device *dev, struct mctrl_gpios *gpios)
 {
 }
 
+static inline void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
+{
+}
+
+static inline void mctrl_gpio_disable_ms(struct mctrl_gpios *gpios)
+{
+}
+
 #endif /* GPIOLIB */
 
 #endif
diff --git a/drivers/video/fbdev/mxc/Makefile b/drivers/video/fbdev/mxc/Makefile
index c91711c..a10d145 100644
--- a/drivers/video/fbdev/mxc/Makefile
+++ b/drivers/video/fbdev/mxc/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL)      += mxcfb_hx8369_wvga.o
 obj-$(CONFIG_FB_MXC_LDB) += ldb.o
 obj-$(CONFIG_FB_MXC_HDMI)			+= mxc_hdmi.o
 obj-$(CONFIG_FB_MXC_EDID)			+= mxc_edid.o
-obj-$(CONFIG_FB_MXC_SYNC_PANEL) += mxc_dispdrv.o mxc_lcdif.o mxc_ipuv3_fb.o
+obj-$(CONFIG_FB_MXC_SYNC_PANEL) += mxc_dispdrv.o mxc_lcdif.o mxc_ipuv3_fb.o mxc_dvi.o
 obj-$(CONFIG_FB_MXC_EINK_PANEL)			+= mxc_epdc_fb.o
 obj-$(CONFIG_FB_MXC_EINK_V2_PANEL)		+= mxc_epdc_v2_fb.o
 obj-$(CONFIG_FB_MXS_SII902X) += mxsfb_sii902x.o
diff --git a/drivers/video/fbdev/mxc/mxc_dvi.c b/drivers/video/fbdev/mxc/mxc_dvi.c
new file mode 100644
index 0000000..42ec4f6
--- /dev/null
+++ b/drivers/video/fbdev/mxc/mxc_dvi.c
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*!
+ * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
+ */
+
+/*!
+ * @file mxc_dvi.c
+ *
+ * @brief MXC DVI driver
+ *
+ * @ingroup Framebuffer
+ */
+
+/*!
+ * Include files
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ipu.h>
+#include <linux/mxcfb.h>
+#include <linux/fsl_devices.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <video/mxc_edid.h>
+#include "mxc_dispdrv.h"
+#include "../edid.h"
+
+#define MXC_EDID_LENGTH (EDID_LENGTH*4)
+
+#define DISPDRV_DVI	"dvi"
+
+struct mxc_dvi_data {
+	struct i2c_client *client;
+	struct platform_device *pdev;
+	struct platform_device *core_pdev;
+	struct mxc_dispdrv_handle *disp_dvi;
+	struct delayed_work det_work;
+	struct fb_info *fbi;
+	struct mxc_edid_cfg edid_cfg;
+	u8 cable_plugin;
+	u8 edid[MXC_EDID_LENGTH];
+
+	u32 ipu_id;
+	u32 disp_id;
+	u32 hp_gpio;
+};
+
+struct i2c_client *dvi_i2c;
+struct mxc_dvi_data *g_dvi;
+
+static ssize_t mxc_dvi_show_state(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mxc_dvi_data *dvi = dev_get_drvdata(dev);
+
+	if (dvi->cable_plugin == 0)
+		strcpy(buf, "plugout\n");
+	else
+		strcpy(buf, "plugin\n");
+
+	return strlen(buf);
+}
+
+static DEVICE_ATTR(cable_state, S_IRUGO, mxc_dvi_show_state, NULL);
+
+static int dvi_update(struct mxc_dvi_data *dvi)
+{
+	if (gpio_is_valid(dvi->hp_gpio))
+		return gpio_get_value(dvi->hp_gpio);
+
+	/* always connected */
+	return 1;
+}
+
+static ssize_t mxc_dvi_show_name(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mxc_dvi_data *dvi = dev_get_drvdata(dev);
+
+	strcpy(buf, dvi->fbi->fix.id);
+	sprintf(buf+strlen(buf), "\n");
+
+	return strlen(buf);
+}
+
+static DEVICE_ATTR(fb_name, S_IRUGO, mxc_dvi_show_name, NULL);
+
+static ssize_t mxc_dvi_show_edid(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mxc_dvi_data *dvi = dev_get_drvdata(dev);
+	int i, j, len = 0;
+
+	for (j = 0; j < MXC_EDID_LENGTH/16; j++) {
+		for (i = 0; i < 16; i++)
+			len += sprintf(buf+len, "0x%02X ",
+					dvi->edid[j*16 + i]);
+		len += sprintf(buf+len, "\n");
+	}
+
+	return len;
+}
+
+static DEVICE_ATTR(edid, S_IRUGO, mxc_dvi_show_edid, NULL);
+
+static void det_worker(struct work_struct *work)
+{
+	struct delayed_work *delay_work = to_delayed_work(work);
+	struct mxc_dvi_data *dvi =
+		container_of(delay_work, struct mxc_dvi_data, det_work);
+	char event_string[16];
+	char *envp[] = { event_string, NULL };
+
+	/* cable connection changes */
+	if (dvi_update(dvi)) {
+		u8 edid_old[MXC_EDID_LENGTH];
+		dvi->cable_plugin = 1;
+		sprintf(event_string, "EVENT=plugin");
+
+		memcpy(edid_old, dvi->edid, MXC_EDID_LENGTH);
+
+		if (mxc_edid_read(dvi->client->adapter, dvi->client->addr,
+				dvi->edid, &dvi->edid_cfg, dvi->fbi) < 0)
+			dev_err(&dvi->client->dev,
+					"MXC dvi: read edid fail\n");
+		else {
+			if (!memcmp(edid_old, dvi->edid, MXC_EDID_LENGTH))
+				dev_info(&dvi->client->dev,
+					"MXC dvi: same edid\n");
+			else if (dvi->fbi->monspecs.modedb_len > 0) {
+				int i;
+				const struct fb_videomode *mode;
+				struct fb_videomode m;
+
+				fb_destroy_modelist(&dvi->fbi->modelist);
+
+				for (i = 0; i < dvi->fbi->monspecs.modedb_len; i++)
+					/*FIXME now we do not support interlaced mode */
+					if (!(dvi->fbi->monspecs.modedb[i].vmode & FB_VMODE_INTERLACED))
+						fb_add_videomode(&dvi->fbi->monspecs.modedb[i],
+								&dvi->fbi->modelist);
+
+				fb_var_to_videomode(&m, &dvi->fbi->var);
+				mode = fb_find_nearest_mode(&m,
+						&dvi->fbi->modelist);
+
+				fb_videomode_to_var(&dvi->fbi->var, mode);
+
+				dvi->fbi->var.activate |= FB_ACTIVATE_FORCE;
+				console_lock();
+				dvi->fbi->flags |= FBINFO_MISC_USEREVENT;
+				fb_set_var(dvi->fbi, &dvi->fbi->var);
+				dvi->fbi->flags &= ~FBINFO_MISC_USEREVENT;
+				console_unlock();
+			}
+		}
+	} else {
+		dvi->cable_plugin = 0;
+		sprintf(event_string, "EVENT=plugout");
+	}
+
+	kobject_uevent_env(&dvi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+}
+
+static irqreturn_t mxc_dvi_detect_handler(int irq, void *data)
+{
+	struct mxc_dvi_data *dvi = data;
+	schedule_delayed_work(&(dvi->det_work), msecs_to_jiffies(300));
+	return IRQ_HANDLED;
+}
+
+static int dvi_init(struct mxc_dispdrv_handle *disp,
+	struct mxc_dispdrv_setting *setting)
+{
+	int ret = 0;
+	struct mxc_dvi_data *dvi = mxc_dispdrv_getdata(disp);
+	bool found = false;
+
+	ret = ipu_di_to_crtc(&dvi->pdev->dev, dvi->ipu_id,
+			     dvi->disp_id, &setting->crtc);
+
+	if (ret < 0)
+		return ret;
+
+	setting->if_fmt = IPU_PIX_FMT_RGB24;
+	dvi->fbi = setting->fbi;
+
+	/* get video mode from edid */
+	INIT_LIST_HEAD(&dvi->fbi->modelist);
+	if (dvi_update(dvi)) {
+		dvi->cable_plugin = 1;
+		/* try to read edid */
+		if (mxc_edid_read(dvi->client->adapter, dvi->client->addr,
+				dvi->edid, &dvi->edid_cfg, dvi->fbi) < 0)
+			dev_warn(&dvi->client->dev, "Can not read edid\n");
+		else if (dvi->fbi->monspecs.modedb_len > 0) {
+			int i;
+			const struct fb_videomode *mode;
+			struct fb_videomode m;
+
+			for (i = 0; i < dvi->fbi->monspecs.modedb_len; i++) {
+				/*FIXME now we do not support interlaced mode */
+				if (!(dvi->fbi->monspecs.modedb[i].vmode
+					& FB_VMODE_INTERLACED))
+					fb_add_videomode(
+						&dvi->fbi->monspecs.modedb[i],
+						&dvi->fbi->modelist);
+			}
+
+			fb_find_mode(&dvi->fbi->var, dvi->fbi, setting->dft_mode_str,
+					NULL, 0, NULL, setting->default_bpp);
+
+			fb_var_to_videomode(&m, &dvi->fbi->var);
+			mode = fb_find_nearest_mode(&m,
+					&dvi->fbi->modelist);
+			fb_videomode_to_var(&dvi->fbi->var, mode);
+			found = 1;
+		}
+	} else
+		dvi->cable_plugin = 0;
+
+	if (!found) {
+		ret = fb_find_mode(&dvi->fbi->var, dvi->fbi, setting->dft_mode_str,
+				NULL, 0, NULL, setting->default_bpp);
+		if (!ret)
+			return -EINVAL;
+	}
+
+	/* cable detection */
+	if (dvi->client->irq) {
+		ret = request_irq(dvi->client->irq, mxc_dvi_detect_handler,
+				IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+				"dvi_det", dvi);
+		if (ret < 0) {
+			dev_warn(&dvi->client->dev,
+				"MXC dvi: cound not request det irq %d\n",
+				dvi->client->irq);
+			goto err;
+		} else {
+			INIT_DELAYED_WORK(&(dvi->det_work), det_worker);
+			ret = device_create_file(&dvi->pdev->dev, &dev_attr_fb_name);
+			if (ret < 0)
+				dev_warn(&dvi->client->dev,
+					"MXC dvi: cound not create sys node for fb name\n");
+			ret = device_create_file(&dvi->pdev->dev, &dev_attr_cable_state);
+			if (ret < 0)
+				dev_warn(&dvi->client->dev,
+					"MXC dvi: cound not create sys node for cable state\n");
+			ret = device_create_file(&dvi->pdev->dev, &dev_attr_edid);
+			if (ret < 0)
+				dev_warn(&dvi->client->dev,
+					"MXC dvi: cound not create sys node for edid\n");
+
+			dev_set_drvdata(&dvi->pdev->dev, dvi);
+		}
+	}
+
+err:
+	return ret;
+}
+
+static void dvi_deinit(struct mxc_dispdrv_handle *disp)
+{
+	struct mxc_dvi_data *dvi = mxc_dispdrv_getdata(disp);
+	free_irq(dvi->client->irq, dvi);
+}
+
+static struct mxc_dispdrv_driver dvi_drv = {
+	.name 	= DISPDRV_DVI,
+	.init 	= dvi_init,
+	.deinit	= dvi_deinit,
+};
+
+static int mxc_dvi_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct mxc_dvi_data *dvi;
+	u32 ipu_id, disp_id, hp_gpio;
+	int ret = 0;
+
+	if (!dvi_i2c)
+		return -EPROBE_DEFER;
+
+	dvi = kzalloc(sizeof(struct mxc_dvi_data), GFP_KERNEL);
+	if (!dvi)
+		return -ENOMEM;
+
+	ret = of_property_read_u32(np, "ipu_id", &ipu_id);
+	if (ret) {
+		dev_dbg(&pdev->dev, "get of property ipu_id fail\n");
+		goto error;
+	}
+	ret = of_property_read_u32(np, "disp_id", &disp_id);
+	if (ret) {
+		dev_dbg(&pdev->dev, "get of property disp_id fail\n");
+		goto error;
+	}
+	ret = of_property_read_u32(np, "hp_gpio", &hp_gpio);
+	if (ret) {
+		dev_dbg(&pdev->dev, "get of property hp_gpio fail\n");
+		goto error;
+	}
+
+	dvi->ipu_id = ipu_id;
+	dvi->disp_id = disp_id;
+	dvi->hp_gpio = hp_gpio;
+
+	dvi->client = dvi_i2c;
+	dvi->pdev = pdev;
+	dvi->disp_dvi = mxc_dispdrv_register(&dvi_drv);
+	mxc_dispdrv_setdata(dvi->disp_dvi, dvi);
+
+	dvi->client->irq = gpio_to_irq(dvi->hp_gpio);
+
+	g_dvi = dvi;
+	platform_set_drvdata(pdev, dvi);
+	printk("Registered MXC DVI as a platform device\n");
+
+	return ret;
+error:
+	kfree(dvi);
+	return ret;
+}
+
+static const struct of_device_id imx_dvi_dt_ids[] = {
+	{ .compatible = "fsl,dvi", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_dvi_dt_ids);
+
+static int mxc_dvi_remove(struct platform_device *pdev)
+{
+	struct mxc_dvi_data *dvi = platform_get_drvdata(pdev);
+	kfree(dvi);
+	g_dvi = NULL;
+
+	return 0;
+}
+static struct platform_driver mxc_dvi_driver = {
+	.driver = {
+		.name = "mxc_dvi",
+		.of_match_table	= imx_dvi_dt_ids,
+	},
+	.probe = mxc_dvi_probe,
+	.remove = mxc_dvi_remove,
+};
+
+static int __init mxc_dvi_init(void)
+{
+	return platform_driver_register(&mxc_dvi_driver);
+}
+module_init(mxc_dvi_init);
+
+static void __exit mxc_dvi_exit(void)
+{
+	platform_driver_unregister(&mxc_dvi_driver);
+}
+module_exit(mxc_dvi_exit);
+
+static int mxc_dvi_i2c_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	if (!i2c_check_functionality(client->adapter,
+				I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
+		return -ENODEV;
+
+	dvi_i2c = client;
+	return 0;
+}
+
+static int mxc_dvi_i2c_remove(struct i2c_client *client)
+{
+	dvi_i2c = NULL;
+	return 0;
+}
+
+static const struct of_device_id imx_dvi_i2c_match[] = {
+	{ .compatible = "fsl,imx6-dvi-i2c", },
+	{ /* sentinel */ }
+};
+
+static const struct i2c_device_id mxc_dvi_i2c_id[] = {
+	{ "mxc_dvi_i2c", 0 },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, mxc_dvi_i2c_id);
+
+static struct i2c_driver mxc_dvi_i2c_driver = {
+	.driver = {
+		   .name = "mxc_dvi_i2c",
+			.of_match_table	= imx_dvi_i2c_match,
+		   },
+	.probe = mxc_dvi_i2c_probe,
+	.remove = mxc_dvi_i2c_remove,
+	.id_table = mxc_dvi_i2c_id,
+};
+
+static int __init mxc_dvi_i2c_init(void)
+{
+	return i2c_add_driver(&mxc_dvi_i2c_driver);
+}
+
+static void __exit mxc_dvi_i2c_exit(void)
+{
+	i2c_del_driver(&mxc_dvi_i2c_driver);
+}
+
+module_init(mxc_dvi_i2c_init);
+module_exit(mxc_dvi_i2c_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC DVI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/mxc/mxc_hdmi.c b/drivers/video/fbdev/mxc/mxc_hdmi.c
index c1b5126..513bda7 100644
--- a/drivers/video/fbdev/mxc/mxc_hdmi.c
+++ b/drivers/video/fbdev/mxc/mxc_hdmi.c
@@ -1260,9 +1260,6 @@ static void mxc_hdmi_phy_init(struct mxc_hdmi *hdmi)
 			|| (hdmi->blank != FB_BLANK_UNBLANK))
 		return;
 
-	if (!hdmi->hdmi_data.video_mode.mDVI)
-		hdmi_enable_overflow_interrupts();
-
 	/*check csc whether needed activated in HDMI mode */
 	cscon = (isColorSpaceConversion(hdmi) &&
 			!hdmi->hdmi_data.video_mode.mDVI);
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 22801b1..cc7dd687 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -33,6 +33,8 @@ extern int of_device_add(struct platform_device *pdev);
 extern int of_device_register(struct platform_device *ofdev);
 extern void of_device_unregister(struct platform_device *ofdev);
 
+extern const void *of_device_get_match_data(const struct device *dev);
+
 extern ssize_t of_device_get_modalias(struct device *dev,
 					char *str, ssize_t len);
 
@@ -57,7 +59,7 @@ void of_dma_configure(struct device *dev, struct device_node *np);
 #else /* CONFIG_OF */
 
 static inline int of_driver_match_device(struct device *dev,
-					 struct device_driver *drv)
+					 const struct device_driver *drv)
 {
 	return 0;
 }
@@ -65,6 +67,11 @@ static inline int of_driver_match_device(struct device *dev,
 static inline void of_device_uevent(struct device *dev,
 			struct kobj_uevent_env *env) { }
 
+static inline const void *of_device_get_match_data(const struct device *dev)
+{
+	return NULL;
+}
+
 static inline int of_device_get_modalias(struct device *dev,
 				   char *str, ssize_t len)
 {
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index a4054f3..8a56912 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -392,6 +392,19 @@ config SND_SOC_IMX_HDMI
 	  Say Y if you want to add support for SoC audio on an i.MX board with
 	  IMX HDMI.
 
+config SND_SOC_IMX_WM8731
+	tristate "SoC Audio support for i.MX boards with WM8731"
+	select SND_SOC_IMX_PCM_DMA
+	select SND_SOC_IMX_AUDMUX
+	select SND_SOC_FSL_SSI
+	select SND_SOC_FSL_UTILS
+	select SND_SOC_WM8731
+	select SND_SIMPLE_CARD
+	help
+	  SoC Audio support for i.MX boards with WM8731
+	  Say Y if you want to add support for Soc audio for the WM8731 chip
+	  CM-FX6 module.
+
 endif # SND_IMX_SOC
 
 endmenu
