Merge remote-tracking branch 'fsl-linux-sdk/imx_3.14.y' into imx_3.14.y_android
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 715db92..a50978f 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -236,6 +236,7 @@
 	imx6ul-14x14-evk-btwifi.dtb \
 	imx6ul-14x14-evk-csi.dtb \
 	imx6ul-9x9-evk.dtb \
+	imx6ul-9x9-evk-btwifi.dtb \
 	imx6ul-9x9-evk-ldo.dtb \
 	imx6ul-9x9-evk-csi.dtb \
 	vf610-cosmic.dtb \
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 79c48b2..d39576b 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -501,6 +501,7 @@
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
 				regulator-always-on;
+				regulator-ramp-delay = <6250>;
 			};
 
 			sw3a_reg: sw3a {
diff --git a/arch/arm/boot/dts/imx6qp-sabresd.dts b/arch/arm/boot/dts/imx6qp-sabresd.dts
index a4f066c..a77b375 100644
--- a/arch/arm/boot/dts/imx6qp-sabresd.dts
+++ b/arch/arm/boot/dts/imx6qp-sabresd.dts
@@ -13,6 +13,10 @@
 	model = "Freescale i.MX6 Quad Plus SABRE Smart Device Board";
 };
 
+&cpu0 {
+	arm-supply = <&sw2_reg>;
+};
+
 &iomuxc {
 	imx6qdl-sabresd {
 		pinctrl_usdhc2: usdhc2grp {
diff --git a/arch/arm/boot/dts/imx6sx-sabreauto-m4.dts b/arch/arm/boot/dts/imx6sx-sabreauto-m4.dts
index 3696c1a..f76bab1 100644
--- a/arch/arm/boot/dts/imx6sx-sabreauto-m4.dts
+++ b/arch/arm/boot/dts/imx6sx-sabreauto-m4.dts
@@ -61,6 +61,7 @@
 };
 
 &qspi_m4 {
+	reg = <0x021e0000 0x4000>;
 	status = "okay";
 };
 
diff --git a/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts b/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts
index 575ed3c..a74d274 100644
--- a/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts
+++ b/arch/arm/boot/dts/imx6sx-sdb-btwifi.dts
@@ -24,7 +24,6 @@
 			regulator-name = "wlreg_on";
 			gpio = <&gpio6 10 0>;
 			startup-delay-us = <100>;
-			regulator-always-on;
 			enable-active-high;
 		};
 	};
@@ -93,6 +92,10 @@
 	bus-width = <1>;
 };
 
+&vcc_sd3 {
+	regulator-always-on;
+};
+
 &usdhc3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_wifi>;
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts b/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts
index 97a21dc..4613799 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk-btwifi.dts
@@ -6,46 +6,5 @@
  * published by the Free Software Foundation.
  */
 
-/*
- * NOTE: This DTS file is written for plugging in Murata Wi-Fi/BT EVK into Slot
- * SD1 and using Murata i.MX InterConnect Ver 2.0 Adapter. Bluetooth UART &
- * control signals are connected via ribbon cable (J1701 connector).
- */
-
 #include "imx6ul-14x14-evk.dts"
-
-/ {
-	regulators {
-		wlreg_on: fixedregulator@100 {
-			compatible = "regulator-fixed";
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
-			regulator-name = "wlreg_on";
-			gpio = <&gpio5 1 0>;
-			startup-delay-us = <100>;
-			enable-active-high;
-		};
-	};
-
-	bcmdhd_wlan_0: bcmdhd_wlan@0 {
-		compatible = "android,bcmdhd_wlan";
-		wlreg_on-supply = <&wlreg_on>;
-	};
-};
-
-&iomuxc {
-	imx6ul-evk-murata-v2 {
-		pinctrl_wifi: wifigrp {
-			fsl,pins = <
-				MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x03029
-			>;
-		};
-	};
-};
-
-&usdhc1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_wifi>;
-	no-1-8-v;
-	wifi-host; /* add hook for SD card detect mechanism for BCMDHD driver */
-};
+#include "imx6ul-evk-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dts b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
index f2ef1f2..6c98f61 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk.dts
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
@@ -284,7 +284,11 @@
 	assigned-clocks = <&clks IMX6UL_CLK_SIM_SEL>;
 	assigned-clock-parents = <&clks IMX6UL_CLK_SIM_PODF>;
 	assigned-clock-rates = <240000000>;
-	pinctrl-assert-gpios = <&gpio4 23 GPIO_ACTIVE_LOW>;
+	/* GPIO_ACTIVE_HIGH/LOW:sim card voltage control
+	 * NCN8025:Vcc = ACTIVE_HIGH?5V:3V
+	 * TDA8035:Vcc = ACTIVE_HIGH?5V:1.8V
+	 */
+	pinctrl-assert-gpios = <&gpio4 23 GPIO_ACTIVE_HIGH>;
 	port = <1>;
 	sven_low_active;
 	status = "okay";
@@ -345,6 +349,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc2>;
 	no-1-8-v;
+	non-removable;
 	keep-power-in-suspend;
 	enable-sdio-wakeup;
 	status = "okay";
@@ -544,10 +549,10 @@
 		pinctrl_sim2_1: sim2grp-1 {
 			fsl,pins = <
 				MX6UL_PAD_CSI_DATA03__SIM2_PORT1_PD		0xb808
-				MX6UL_PAD_CSI_DATA04__SIM2_PORT1_CLK		0x31
-				MX6UL_PAD_CSI_DATA05__SIM2_PORT1_RST_B		0xb808
-				MX6UL_PAD_CSI_DATA06__SIM2_PORT1_SVEN		0xb808
-				MX6UL_PAD_CSI_DATA07__SIM2_PORT1_TRXD		0xb809
+				MX6UL_PAD_CSI_DATA04__SIM2_PORT1_CLK		0x11
+				MX6UL_PAD_CSI_DATA05__SIM2_PORT1_RST_B		0xb810
+				MX6UL_PAD_CSI_DATA06__SIM2_PORT1_SVEN		0xb810
+				MX6UL_PAD_CSI_DATA07__SIM2_PORT1_TRXD		0xb811
 				MX6UL_PAD_CSI_DATA02__GPIO4_IO23		0x3008
 			>;
 		};
diff --git a/arch/arm/boot/dts/imx6ul-9x9-evk-btwifi.dts b/arch/arm/boot/dts/imx6ul-9x9-evk-btwifi.dts
new file mode 100644
index 0000000..de89052
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-9x9-evk-btwifi.dts
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "imx6ul-9x9-evk.dts"
+#include "imx6ul-evk-btwifi.dtsi"
diff --git a/arch/arm/boot/dts/imx6ul-9x9-evk.dts b/arch/arm/boot/dts/imx6ul-9x9-evk.dts
index 3b9047c..e04ff80 100644
--- a/arch/arm/boot/dts/imx6ul-9x9-evk.dts
+++ b/arch/arm/boot/dts/imx6ul-9x9-evk.dts
@@ -758,7 +758,7 @@
 	pinctrl-0 = <&pinctrl_usdhc1>;
 	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
 	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
-	cd-gpios = <&gpio1 19 0>;
+	cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
 	keep-power-in-suspend;
 	enable-sdio-wakeup;
 	vmmc-supply = <&reg_sd1_vmmc>;
@@ -769,6 +769,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc2>;
 	no-1-8-v;
+	non-removable;
 	keep-power-in-suspend;
 	enable-sdio-wakeup;
 	status = "okay";
diff --git a/arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi b/arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi
new file mode 100644
index 0000000..99a67cf
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ul-evk-btwifi.dtsi
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * NOTE: This DTS file is written for plugging in Murata Wi-Fi/BT EVK into Slot
+ * SD1 and using Murata i.MX InterConnect Ver 2.0 Adapter. Bluetooth UART &
+ * control signals are connected via ribbon cable (J1701 connector).
+ */
+
+/ {
+	regulators {
+		wlreg_on: fixedregulator@100 {
+			compatible = "regulator-fixed";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-name = "wlreg_on";
+			gpio = <&gpio5 1 0>;
+			startup-delay-us = <100>;
+			enable-active-high;
+		};
+	};
+
+	bcmdhd_wlan_0: bcmdhd_wlan@0 {
+		compatible = "android,bcmdhd_wlan";
+		wlreg_on-supply = <&wlreg_on>;
+	};
+};
+
+&iomuxc {
+	imx6ul-evk-murata-v2 {
+		pinctrl_wifi: wifigrp {
+			fsl,pins = <
+				MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01 0x03029
+			>;
+		};
+	};
+};
+
+&reg_sd1_vmmc {
+	regulator-always-on;
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_wifi>;
+	no-1-8-v;
+	wifi-host; /* add hook for SD card detect mechanism for BCMDHD driver */
+};
diff --git a/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-m4.dts b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-m4.dts
index 46b359f..1c8de62 100644
--- a/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-m4.dts
+++ b/arch/arm/boot/dts/imx7d-12x12-lpddr3-arm2-m4.dts
@@ -5,6 +5,10 @@
 	memory {
 		linux,usable-memory = <0x80000000 0x3ff00000>;
 	};
+
+	gpio-keys {
+		status = "disabled";
+	};
 };
 
 &adc1 {
@@ -15,17 +19,6 @@
 	status = "disabled";
 };
 
-&iomuxc {
-	imx7d-12x12-lpddr3-arm2 {
-		pinctrl_uart2_1: uart2grp-1 {
-			fsl,pins = <
-				MX7D_PAD_UART2_RX_DATA__UART2_DCE_RX 	0x79
-				MX7D_PAD_UART2_TX_DATA__UART2_DCE_TX 	0x79
-			>;
-		};
-	};
-};
-
 &gpt3 {
 	status = "disabled";
 };
@@ -47,11 +40,7 @@
 };
 
 &uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
-	assigned-clocks = <&clks IMX7D_UART2_ROOT_SRC>;
-	assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
-	status = "okay";
+	status = "disabled";
 };
 
 &wdog3{
diff --git a/arch/arm/boot/dts/imx7d-sdb-epdc.dts b/arch/arm/boot/dts/imx7d-sdb-epdc.dts
index acdbf76..1cef0c3 100644
--- a/arch/arm/boot/dts/imx7d-sdb-epdc.dts
+++ b/arch/arm/boot/dts/imx7d-sdb-epdc.dts
@@ -20,6 +20,10 @@
 	status = "disabled";
 };
 
+&flexcan2 {
+	status = "disabled";
+};
+
 &max17135 {
         status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx7d-sdb-m4.dts b/arch/arm/boot/dts/imx7d-sdb-m4.dts
index d0bb049..a6642a8 100644
--- a/arch/arm/boot/dts/imx7d-sdb-m4.dts
+++ b/arch/arm/boot/dts/imx7d-sdb-m4.dts
@@ -13,6 +13,11 @@
 		linux,usable-memory = <0x80000000 0x3ff00000>;
 		reg = <0x80000000 0x80000000>;
 	};
+
+	m4_tcm: tcml@007f8000 {
+		compatible = "fsl, m4_tcml";
+		reg = <0x007f8000 0x8000>;
+	};
 };
 
 &adc1 {
@@ -31,17 +36,6 @@
 	status = "disabled";
 };
 
-&iomuxc {
-	imx7d-sdb {
-		pinctrl_uart2_1: uart2grp-1 {
-			fsl,pins = <
-				MX7D_PAD_UART2_RX_DATA__UART2_DCE_RX    0x79
-				MX7D_PAD_UART2_TX_DATA__UART2_DCE_TX    0x79
-			>;
-		};
-	};
-};
-
 &gpt3 {
 	status = "disabled";
 };
@@ -63,11 +57,7 @@
 };
 
 &uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
-	assigned-clocks = <&clks IMX7D_UART2_ROOT_SRC>;
-	assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
-	status = "okay";
+	status = "disabled";
 };
 
 &wdog3{
diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
index 2086b70..d84d1a7 100644
--- a/arch/arm/boot/dts/imx7d-sdb.dts
+++ b/arch/arm/boot/dts/imx7d-sdb.dts
@@ -74,7 +74,7 @@
 			regulator-name = "can2-3v3";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
-			gpio = <&gpio1 7 GPIO_ACTIVE_LOW>;
+			gpio = <&gpio2 14 GPIO_ACTIVE_LOW>;
 		};
 
 		reg_vref_1v8: regulator@3 {
@@ -977,7 +977,7 @@
 		pinctrl_hog_2: hoggrp-2 {
 			fsl,pins = <
 				MX7D_PAD_GPIO1_IO05__GPIO1_IO5	0x14
-				MX7D_PAD_GPIO1_IO07__GPIO1_IO7	0x59  /* CAN_STBY */
+				MX7D_PAD_EPDC_DATA14__GPIO2_IO14 0x59  /* CAN_STBY */
 				MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_B 0x74
 			>;
 		};
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index abdf1df..e3315f3 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -152,18 +152,15 @@
 CONFIG_USB_RTL8152=m
 CONFIG_USB_USBNET=m
 CONFIG_USB_NET_CDC_EEM=m
-CONFIG_ATH_CARDS=y
-CONFIG_ATH6KL=m
-CONFIG_ATH6KL_SDIO=m
 CONFIG_BCMDHD=m
 CONFIG_BCMDHD_SDIO=y
 CONFIG_BCMDHD_FW_PATH="/lib/firmware/bcm/fw_bcmdhd.bin"
 CONFIG_BCMDHD_NVRAM_PATH="/lib/firmware/bcm/bcmdhd.cal"
+# CONFIG_RTL_CARDS is not set
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
-CONFIG_KEYBOARD_SNVS_PWRKEY=y
 CONFIG_KEYBOARD_IMX=y
 CONFIG_MOUSE_PS2=m
 CONFIG_MOUSE_PS2_ELANTECH=y
@@ -341,7 +338,6 @@
 CONFIG_MXC_GPU_VIV=y
 CONFIG_MXC_IPU_V3_PRE=y
 CONFIG_MXC_MIPI_CSI2=y
-CONFIG_MXC_MLB150=m
 CONFIG_MXC_SIM=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
diff --git a/arch/arm/mach-imx/busfreq-imx.c b/arch/arm/mach-imx/busfreq-imx.c
index 784c77a..079c90b 100644
--- a/arch/arm/mach-imx/busfreq-imx.c
+++ b/arch/arm/mach-imx/busfreq-imx.c
@@ -1303,6 +1303,9 @@
 			high_bus_count++;
 	}
 
+	if (cpu_is_imx7d() && imx_src_is_m4_enabled())
+		high_bus_count++;
+
 	if (err) {
 		dev_err(busfreq_dev, "Busfreq init of ddr controller failed\n");
 		return err;
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index a41a000..cb3873f 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -101,6 +101,8 @@
 void mcc_receive_from_mu_buffer(unsigned int index, unsigned int *data);
 void mcc_send_via_mu_buffer(unsigned int index, unsigned int data);
 bool imx_mu_is_m4_in_low_freq(void);
+bool imx_mu_is_m4_in_stop(void);
+int imx_mu_lpm_ready(bool ready);
 unsigned int imx_gpcv2_is_mf_mix_off(void);
 int imx_gpc_mf_power_on(unsigned int irq, unsigned int on);
 #ifdef CONFIG_HAVE_IMX_GPCV2
diff --git a/arch/arm/mach-imx/gpcv2.c b/arch/arm/mach-imx/gpcv2.c
index dbe99b7..56010df 100644
--- a/arch/arm/mach-imx/gpcv2.c
+++ b/arch/arm/mach-imx/gpcv2.c
@@ -116,8 +116,9 @@
 	if (index >= MAX_SLOT_NUMBER)
 		pr_err("Invalid slot index!\n");
 	/* set slot */
-	writel_relaxed((mode + 1) << (m_core * 2), gpc_base +
-		GPC_SLOT0_CFG + index * 4);
+	writel_relaxed(readl_relaxed(gpc_base + GPC_SLOT0_CFG + index * 4)|
+		((mode + 1) << (m_core * 2)),
+		gpc_base + GPC_SLOT0_CFG + index * 4);
 
 	if (ack) {
 		/* set ack */
@@ -306,16 +307,16 @@
 	if (pdn) {
 		imx_gpcv2_set_slot_ack(0, CORE0_A7, false, false);
 		if (num_online_cpus() > 1)
-			imx_gpcv2_set_slot_ack(1, CORE1_A7, false, false);
-		imx_gpcv2_set_slot_ack(2, SCU_A7, false, true);
+			imx_gpcv2_set_slot_ack(2, CORE1_A7, false, false);
+		imx_gpcv2_set_slot_ack(3, SCU_A7, false, true);
 		imx_gpcv2_set_slot_ack(6, SCU_A7, true, false);
 		imx_gpcv2_set_slot_ack(7, CORE0_A7, true, false);
 		if (num_online_cpus() > 1)
 			imx_gpcv2_set_slot_ack(8, CORE1_A7, true, true);
 	} else {
 		writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 0 * 0x4);
-		writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 1 * 0x4);
 		writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 2 * 0x4);
+		writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 3 * 0x4);
 		writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 6 * 0x4);
 		writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 7 * 0x4);
 		writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + 8 * 0x4);
@@ -352,7 +353,9 @@
 			return;
 
 	pr_info("Turn off Mega/Fast mix in DSM\n");
-	imx_gpcv2_set_mix_phy_gate_by_lpm(1, 5);
+
+	imx_gpcv2_set_slot_ack(1, FAST_MEGA_MIX, false, false);
+	imx_gpcv2_set_slot_ack(5, FAST_MEGA_MIX, true, false);
 	imx_gpcv2_set_m_core_pgc(true, GPC_PGC_FM);
 }
 
@@ -399,8 +402,9 @@
 		 */
 		imx_gpcv2_set_slot_ack(0, CORE0_A7, false, false);
 		imx_gpcv2_set_slot_ack(2, SCU_A7, false, true);
-
-		imx_gpcv2_mf_mix_off();
+		if ((!imx_src_is_m4_enabled()) ||
+		    (imx_src_is_m4_enabled() && imx_mu_is_m4_in_stop()))
+			 imx_gpcv2_mf_mix_off();
 
 		imx_gpcv2_set_slot_ack(6, SCU_A7, true, false);
 		imx_gpcv2_set_slot_ack(7, CORE0_A7, true, true);
@@ -427,9 +431,10 @@
 	val = readl_relaxed(gpc_base + GPC_LPCR_A7_BSC);
 	val |= BM_LPCR_A7_BSC_IRQ_SRC_A7_WAKEUP;
 	writel_relaxed(val, gpc_base + GPC_LPCR_A7_BSC);
-	/* mask m4 dsm trigger */
-	writel_relaxed(readl_relaxed(gpc_base + GPC_LPCR_M4) |
-		BM_LPCR_M4_MASK_DSM_TRIGGER, gpc_base + GPC_LPCR_M4);
+	/* mask m4 dsm trigger if M4 not enabled*/
+	if (!imx_src_is_m4_enabled())
+		writel_relaxed(readl_relaxed(gpc_base + GPC_LPCR_M4) |
+			BM_LPCR_M4_MASK_DSM_TRIGGER, gpc_base + GPC_LPCR_M4);
 	/* set mega/fast mix in A7 domain */
 	writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_MAPPING);
 	/* set SCU timing */
@@ -437,8 +442,10 @@
 		gpc_base + GPC_PGC_SCU_TIMING);
 
 	val = readl_relaxed(gpc_base + GPC_SLPCR);
-	val &= ~(BM_SLPCR_EN_DSM | BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN |
-		BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY);
+	val &= ~(BM_SLPCR_EN_DSM);
+	if (!imx_src_is_m4_enabled())
+		val &= ~(BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN |
+			BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY);
 	val |= BM_SLPCR_EN_A7_FASTWUP_WAIT_MODE;
 	writel_relaxed(val, gpc_base + GPC_SLPCR);
 
@@ -458,7 +465,11 @@
 	imx_gpcv2_set_m_core_pgc(false, GPC_PGC_SCU);
 	imx_gpcv2_set_m_core_pgc(false, GPC_PGC_FM);
 	for (i = 0; i < MAX_SLOT_NUMBER; i++)
+	{
+		if (i==1||i==4) /* skip slts m4 uses */
+			continue;
 		writel_relaxed(0x0, gpc_base + GPC_SLOT0_CFG + i * 0x4);
+        }
 	writel_relaxed(BM_GPC_PGC_ACK_SEL_A7_DUMMY_PUP_ACK |
 		BM_GPC_PGC_ACK_SEL_A7_DUMMY_PDN_ACK,
 		gpc_base + GPC_PGC_ACK_SEL_A7);
@@ -647,9 +658,10 @@
 	val = readl_relaxed(gpc_base + GPC_LPCR_A7_BSC);
 	val |= BM_LPCR_A7_BSC_IRQ_SRC_A7_WAKEUP;
 	writel_relaxed(val, gpc_base + GPC_LPCR_A7_BSC);
-	/* mask m4 dsm trigger */
-	writel_relaxed(readl_relaxed(gpc_base + GPC_LPCR_M4) |
-		BM_LPCR_M4_MASK_DSM_TRIGGER, gpc_base + GPC_LPCR_M4);
+	/* mask m4 dsm trigger if M4 not enabled*/
+	if (!imx_src_is_m4_enabled())
+		writel_relaxed(readl_relaxed(gpc_base + GPC_LPCR_M4) |
+			BM_LPCR_M4_MASK_DSM_TRIGGER, gpc_base + GPC_LPCR_M4);
 	/* set mega/fast mix in A7 domain */
 	writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_MAPPING);
 	/* set SCU timing */
@@ -660,8 +672,10 @@
 		gpc_base + GPC_PGC_ACK_SEL_A7);
 
 	val = readl_relaxed(gpc_base + GPC_SLPCR);
-	val &= ~(BM_SLPCR_EN_DSM | BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN |
-		BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY);
+	val &= ~(BM_SLPCR_EN_DSM);
+	if (!imx_src_is_m4_enabled())
+		val &= ~(BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN |
+			BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY);
 	val |= BM_SLPCR_EN_A7_FASTWUP_WAIT_MODE;
 	writel_relaxed(val, gpc_base + GPC_SLPCR);
 
diff --git a/arch/arm/mach-imx/mu.c b/arch/arm/mach-imx/mu.c
index 56ab9ce..69ae718 100644
--- a/arch/arm/mach-imx/mu.c
+++ b/arch/arm/mach-imx/mu.c
@@ -47,6 +47,11 @@
 #define MU_LPM_M4_WAKEUP_ENABLE_MASK	0xF
 #define MU_LPM_M4_WAKEUP_ENABLE_SHIFT	0x0
 
+#define MU_LPM_M4_A7_READY              0xFFFFAAAA
+#define MU_LPM_M4_RUN_MODE	        0x5A5A0001
+#define MU_LPM_M4_WAIT_MODE	        0x5A5A0002
+#define MU_LPM_M4_STOP_MODE	        0x5A5A0003
+
 struct imx_mu_rpmsg_box {
 	const char *name;
 	struct blocking_notifier_head notifier;
@@ -62,6 +67,7 @@
 static struct delayed_work mu_work, rpmsg_work;
 static u32 m4_wake_irqs[4];
 static bool m4_freq_low;
+static bool m4_in_stop;
 
 struct imx_sema4_mutex *mcc_shm_ptr;
 unsigned int imx_mcc_buffer_freed = 0, imx_mcc_buffer_queued = 0;
@@ -70,6 +76,11 @@
 /* Used for blocking recv */
 static DECLARE_WAIT_QUEUE_HEAD(buffer_queued_wait_queue);
 
+bool imx_mu_is_m4_in_stop(void)
+{
+	return m4_in_stop;
+}
+
 bool imx_mu_is_m4_in_low_freq(void)
 {
 	return m4_freq_low;
@@ -163,10 +174,18 @@
 	pr_debug("receive M4 message 0x%x\n", m4_message);
 
 	switch (m4_message) {
+	case MU_LPM_M4_RUN_MODE:
+	case MU_LPM_M4_WAIT_MODE:
+		m4_in_stop = false;
+		break;
+	case MU_LPM_M4_STOP_MODE:
+		m4_in_stop = true;
+		break;
 	case MU_LPM_M4_REQUEST_HIGH_BUS:
 		request_bus_freq(BUS_FREQ_HIGH);
 #ifdef CONFIG_SOC_IMX6SX
-		imx6sx_set_m4_highfreq(true);
+		if (cpu_is_imx6sx())
+			imx6sx_set_m4_highfreq(true);
 #endif
 		imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX,
 			MU_LPM_BUS_HIGH_READY_FOR_M4);
@@ -175,10 +194,12 @@
 	case MU_LPM_M4_RELEASE_HIGH_BUS:
 		release_bus_freq(BUS_FREQ_HIGH);
 #ifdef CONFIG_SOC_IMX6SX
-		imx6sx_set_m4_highfreq(false);
+		if (cpu_is_imx6sx()) {
+			imx6sx_set_m4_highfreq(false);
+			imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX,
+				MU_LPM_M4_FREQ_CHANGE_READY);
+		}
 #endif
-		imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX,
-			MU_LPM_M4_FREQ_CHANGE_READY);
 		m4_freq_low = true;
 		break;
 	default:
@@ -219,6 +240,18 @@
 	return imx_mu_send_message(MU_RPMSG_HANDSHAKE_INDEX, rpmsg);
 }
 
+int imx_mu_lpm_ready(bool ready)
+{
+	u32 val;
+
+	val = readl_relaxed(mu_base + MU_ACR);
+	if (ready)
+		writel_relaxed(val | BIT(0), mu_base + MU_ACR);
+	else
+		writel_relaxed(val & ~BIT(0), mu_base + MU_ACR);
+	return 0;
+}
+
 int imx_mu_rpmsg_register_nb(const char *name, struct notifier_block *nb)
 {
 	if ((name == NULL) || (nb == NULL))
@@ -566,6 +599,12 @@
 		/* enable the bit31(GIE3) of MU_ACR, used for MCC */
 		writel_relaxed(readl_relaxed(mu_base + MU_ACR) | BIT(31),
 			mu_base + MU_ACR);
+		INIT_DELAYED_WORK(&mu_work, mu_work_handler);
+		INIT_DELAYED_WORK(&rpmsg_work, rpmsg_work_handler);
+		/* enable the bit26(RIE1) of MU_ACR */
+		writel_relaxed(readl_relaxed(mu_base + MU_ACR) |
+			BIT(26) | BIT(27), mu_base + MU_ACR);
+		imx_mu_lpm_ready(true);
 	} else {
 		INIT_DELAYED_WORK(&mu_work, mu_work_handler);
 
diff --git a/arch/arm/mach-imx/pm-imx7.c b/arch/arm/mach-imx/pm-imx7.c
index cd6b918..00bb02a 100644
--- a/arch/arm/mach-imx/pm-imx7.c
+++ b/arch/arm/mach-imx/pm-imx7.c
@@ -9,6 +9,7 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+#include <linux/busfreq-imx.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -115,6 +116,11 @@
 #define GPIO_IMR		0x14
 #define GPIO_EDGE		0x1c
 
+#define M4RCR			0x0C
+#define M4_SP_OFF		0x00
+#define M4_PC_OFF		0x04
+#define M4_RCR_HALT		0xAB
+#define M4_RCR_GO		0xAA
 extern unsigned long iram_tlb_base_addr;
 extern unsigned long iram_tlb_phys_addr;
 
@@ -123,6 +129,11 @@
 static unsigned int ocram_size;
 static unsigned int *lpm_ocram_saved_in_ddr;
 static void __iomem *lpm_ocram_base;
+
+static unsigned int *lpm_m4tcm_saved_in_ddr;
+static void __iomem *lpm_m4tcm_base;
+static void __iomem *m4_bootrom_base;
+
 static unsigned int lpm_ocram_size;
 static void __iomem *ccm_base;
 static void __iomem *lpsr_base;
@@ -693,6 +704,10 @@
 		imx_anatop_pre_suspend();
 		imx_gpcv2_pre_suspend(true);
 		if (imx_gpcv2_is_mf_mix_off()) {
+			/* stop m4 if mix will also be shutdown */
+			if (imx_src_is_m4_enabled() && imx_mu_is_m4_in_stop())
+				writel(M4_RCR_HALT,
+					pm_info->src_base.vbase + M4RCR);
 			imx7_console_save(console_saved_reg);
 			memcpy(ocram_saved_in_ddr, ocram_base, ocram_size);
 			if (lpsr_enabled) {
@@ -726,6 +741,24 @@
 			imx7_pm_is_resume_from_lpsr()) {
 			memcpy(ocram_base, ocram_saved_in_ddr, ocram_size);
 			imx7_console_restore(console_saved_reg);
+			if (imx_src_is_m4_enabled() && imx_mu_is_m4_in_stop()) {
+				/* restore M4 image */
+				memcpy(lpm_m4tcm_base,
+				    lpm_m4tcm_saved_in_ddr, SZ_32K);
+				/* set sp from word in the image */
+				writel(*(lpm_m4tcm_saved_in_ddr),
+				    m4_bootrom_base + M4_SP_OFF);
+				/* set PC from next word */
+				writel(*(lpm_m4tcm_saved_in_ddr+1),
+				    m4_bootrom_base + M4_PC_OFF);
+				/* kick m4 to enable */
+				writel(M4_RCR_GO,
+					pm_info->src_base.vbase + M4RCR);
+                                /* offset high bus count for m4 image */
+                                request_bus_freq(BUS_FREQ_HIGH);
+				/* gpc wakeup */
+				imx_mu_lpm_ready(true);
+			}
 		}
 		/* clear LPSR resume address */
 		imx7_pm_set_lpsr_resume_addr(0);
@@ -1016,7 +1049,27 @@
 {
 	struct device_node *np;
 	struct resource res;
+	if (imx_src_is_m4_enabled()) {
+		/* map the 32K of M4 TCM */
+		np = of_find_node_by_path(
+			"/tcml@007f8000");
+		if (np)
+			lpm_m4tcm_base = of_iomap(np, 0);
+		WARN_ON(!lpm_m4tcm_base);
 
+		/* map the m4 bootrom from dtb */
+		np = of_find_node_by_path(
+			"/soc/sram@00180000");
+		if (np)
+			m4_bootrom_base = of_iomap(np, 0);
+		WARN_ON(!m4_bootrom_base);
+
+		lpm_m4tcm_saved_in_ddr = kzalloc(SZ_32K, GFP_KERNEL);
+		WARN_ON(!lpm_m4tcm_saved_in_ddr);
+
+		/* save M4 Image to DDR */
+		memcpy(lpm_m4tcm_saved_in_ddr, lpm_m4tcm_base, SZ_32K);
+	}
 	np = of_find_compatible_node(NULL, NULL, "fsl,lpm-sram");
 	if (of_get_property(np, "fsl,enable-lpsr", NULL))
 		lpsr_enabled = true;
diff --git a/arch/arm/mach-imx/suspend-imx7.S b/arch/arm/mach-imx/suspend-imx7.S
index 34910ad..ea07123 100644
--- a/arch/arm/mach-imx/suspend-imx7.S
+++ b/arch/arm/mach-imx/suspend-imx7.S
@@ -551,6 +551,12 @@
 
 	restore_ttbr1
 standby_out:
+	/* make sure SNVS clk is disabled */
+	ldr	r11, [r0, #PM_INFO_MX7_CCM_V_OFFSET]
+	add	r11, r11, #0x4000
+	ldr	r7, =0x0
+	str	r7, [r11, #CCM_SNVS_LPCG]
+
 	pop	{r4-r12}
 	/* return to suspend finish */
 	mov	pc, lr
@@ -585,6 +591,11 @@
 dsm_ddr_self_refresh_out:
 	ddrc_exit_self_refresh
 dsm_ddr_retention_out:
+	/* make sure SNVS clk is disabled */
+	ldr	r11, [r0, #PM_INFO_MX7_CCM_P_OFFSET]
+	add	r11, r11, #0x4000
+	ldr	r7, =0x0
+	str	r7, [r11, #CCM_SNVS_LPCG]
 
 	mov	pc, lr
 ENDPROC(imx7_suspend)
diff --git a/drivers/dma/pxp/pxp_dma_v2.c b/drivers/dma/pxp/pxp_dma_v2.c
index 5225bcf..48d751d3 100644
--- a/drivers/dma/pxp/pxp_dma_v2.c
+++ b/drivers/dma/pxp/pxp_dma_v2.c
@@ -1319,6 +1319,7 @@
 
 	if (list_empty(&head)) {
 		pxp->pxp_ongoing = 0;
+		pxp->lut_state = 0;
 		spin_unlock_irqrestore(&pxp->lock, flags);
 		return IRQ_NONE;
 	}
@@ -1349,6 +1350,7 @@
 
 	complete(&pxp->complete);
 	pxp->pxp_ongoing = 0;
+	pxp->lut_state = 0;
 	mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms));
 
 	spin_unlock_irqrestore(&pxp->lock, flags);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 47a4bd3..79d5235 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2155,7 +2155,7 @@
 		y = 0;
 		for (x = 1; x && x <= max_qty && max_qty - x >= qty; x <<= 1) {
 			timeout = mmc_erase_timeout(card, arg, qty + x);
-			if (timeout > host->max_discard_to)
+			if (timeout > host->max_busy_timeout)
 				break;
 			if (timeout < last_timeout)
 				break;
@@ -2187,7 +2187,7 @@
 	struct mmc_host *host = card->host;
 	unsigned int max_discard, max_trim;
 
-	if (!host->max_discard_to)
+	if (!host->max_busy_timeout)
 		return UINT_MAX;
 
 	/*
@@ -2207,7 +2207,7 @@
 		max_discard = 0;
 	}
 	pr_debug("%s: calculated max. discard sectors %u for timeout %u ms\n",
-		 mmc_hostname(host), max_discard, host->max_discard_to);
+		 mmc_hostname(host), max_discard, host->max_busy_timeout);
 	return max_discard;
 }
 EXPORT_SYMBOL(mmc_calc_max_discard);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 0731155..abff3c3 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -273,6 +273,97 @@
 	card->ext_csd.card_type = card_type;
 }
 
+static void mmc_manage_enhanced_area(struct mmc_card *card, u8 *ext_csd)
+{
+	u8 hc_erase_grp_sz, hc_wp_grp_sz;
+
+	/*
+	 * Disable these attributes by default
+	 */
+	card->ext_csd.enhanced_area_offset = -EINVAL;
+	card->ext_csd.enhanced_area_size = -EINVAL;
+
+	/*
+	 * Enhanced area feature support -- check whether the eMMC
+	 * card has the Enhanced area enabled.  If so, export enhanced
+	 * area offset and size to user by adding sysfs interface.
+	 */
+	if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
+	    (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
+		if (card->ext_csd.partition_setting_completed) {
+			hc_erase_grp_sz =
+				ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+			hc_wp_grp_sz =
+				ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+
+			/*
+			 * calculate the enhanced data area offset, in bytes
+			 */
+			card->ext_csd.enhanced_area_offset =
+				(ext_csd[139] << 24) + (ext_csd[138] << 16) +
+				(ext_csd[137] << 8) + ext_csd[136];
+			if (mmc_card_blockaddr(card))
+				card->ext_csd.enhanced_area_offset <<= 9;
+			/*
+			 * calculate the enhanced data area size, in kilobytes
+			 */
+			card->ext_csd.enhanced_area_size =
+				(ext_csd[142] << 16) + (ext_csd[141] << 8) +
+				ext_csd[140];
+			card->ext_csd.enhanced_area_size *=
+				(size_t)(hc_erase_grp_sz * hc_wp_grp_sz);
+			card->ext_csd.enhanced_area_size <<= 9;
+		} else {
+			pr_warn("%s: defines enhanced area without partition setting complete\n",
+				mmc_hostname(card->host));
+		}
+	}
+}
+
+static void mmc_manage_gp_partitions(struct mmc_card *card, u8 *ext_csd)
+{
+	int idx;
+	u8 hc_erase_grp_sz, hc_wp_grp_sz;
+	unsigned int part_size;
+
+	/*
+	 * General purpose partition feature support --
+	 * If ext_csd has the size of general purpose partitions,
+	 * set size, part_cfg, partition name in mmc_part.
+	 */
+	if (ext_csd[EXT_CSD_PARTITION_SUPPORT] &
+	    EXT_CSD_PART_SUPPORT_PART_EN) {
+		hc_erase_grp_sz =
+			ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+		hc_wp_grp_sz =
+			ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+
+		for (idx = 0; idx < MMC_NUM_GP_PARTITION; idx++) {
+			if (!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3] &&
+			    !ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] &&
+			    !ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2])
+				continue;
+			if (card->ext_csd.partition_setting_completed == 0) {
+				pr_warn("%s: has partition size defined without partition complete\n",
+					mmc_hostname(card->host));
+				break;
+			}
+			part_size =
+				(ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2]
+				<< 16) +
+				(ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1]
+				<< 8) +
+				ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3];
+			part_size *= (size_t)(hc_erase_grp_sz *
+				hc_wp_grp_sz);
+			mmc_part_add(card, part_size << 19,
+				EXT_CSD_PART_CONFIG_ACC_GP0 + idx,
+				"gp%d", idx, false,
+				MMC_BLK_DATA_AREA_GP);
+		}
+	}
+}
+
 /*
  * Decode extended CSD.
  */
@@ -280,7 +371,6 @@
 {
 	int err = 0, idx;
 	unsigned int part_size;
-	u8 hc_erase_grp_sz = 0, hc_wp_grp_sz = 0;
 
 	BUG_ON(!card);
 
@@ -382,80 +472,16 @@
 		ext_csd[EXT_CSD_TRIM_MULT];
 	card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
 	if (card->ext_csd.rev >= 4) {
-		/*
-		 * Enhanced area feature support -- check whether the eMMC
-		 * card has the Enhanced area enabled.  If so, export enhanced
-		 * area offset and size to user by adding sysfs interface.
-		 */
-		if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
-		    (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
-			hc_erase_grp_sz =
-				ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
-			hc_wp_grp_sz =
-				ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+		if (ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED] &
+		    EXT_CSD_PART_SETTING_COMPLETED)
+			card->ext_csd.partition_setting_completed = 1;
+		else
+			card->ext_csd.partition_setting_completed = 0;
 
-			card->ext_csd.enhanced_area_en = 1;
-			/*
-			 * calculate the enhanced data area offset, in bytes
-			 */
-			card->ext_csd.enhanced_area_offset =
-				(ext_csd[139] << 24) + (ext_csd[138] << 16) +
-				(ext_csd[137] << 8) + ext_csd[136];
-			if (mmc_card_blockaddr(card))
-				card->ext_csd.enhanced_area_offset <<= 9;
-			/*
-			 * calculate the enhanced data area size, in kilobytes
-			 */
-			card->ext_csd.enhanced_area_size =
-				(ext_csd[142] << 16) + (ext_csd[141] << 8) +
-				ext_csd[140];
-			card->ext_csd.enhanced_area_size *=
-				(size_t)(hc_erase_grp_sz * hc_wp_grp_sz);
-			card->ext_csd.enhanced_area_size <<= 9;
-		} else {
-			/*
-			 * If the enhanced area is not enabled, disable these
-			 * device attributes.
-			 */
-			card->ext_csd.enhanced_area_offset = -EINVAL;
-			card->ext_csd.enhanced_area_size = -EINVAL;
-		}
+		mmc_manage_enhanced_area(card, ext_csd);
 
-		/*
-		 * General purpose partition feature support --
-		 * If ext_csd has the size of general purpose partitions,
-		 * set size, part_cfg, partition name in mmc_part.
-		 */
-		if (ext_csd[EXT_CSD_PARTITION_SUPPORT] &
-			EXT_CSD_PART_SUPPORT_PART_EN) {
-			if (card->ext_csd.enhanced_area_en != 1) {
-				hc_erase_grp_sz =
-					ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
-				hc_wp_grp_sz =
-					ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+		mmc_manage_gp_partitions(card, ext_csd);
 
-				card->ext_csd.enhanced_area_en = 1;
-			}
-
-			for (idx = 0; idx < MMC_NUM_GP_PARTITION; idx++) {
-				if (!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3] &&
-				!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] &&
-				!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2])
-					continue;
-				part_size =
-				(ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2]
-					<< 16) +
-				(ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1]
-					<< 8) +
-				ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3];
-				part_size *= (size_t)(hc_erase_grp_sz *
-					hc_wp_grp_sz);
-				mmc_part_add(card, part_size << 19,
-					EXT_CSD_PART_CONFIG_ACC_GP0 + idx,
-					"gp%d", idx, false,
-					MMC_BLK_DATA_AREA_GP);
-			}
-		}
 		card->ext_csd.sec_trim_mult =
 			ext_csd[EXT_CSD_SEC_TRIM_MULT];
 		card->ext_csd.sec_erase_mult =
@@ -1448,7 +1474,7 @@
 	 * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
 	 * bit.  This bit will be lost every time after a reset or power off.
 	 */
-	if (card->ext_csd.enhanced_area_en ||
+	if (card->ext_csd.partition_setting_completed ||
 	    (card->ext_csd.rev >= 3 && (host->caps2 & MMC_CAP2_HC_ERASE_SZ))) {
 		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 				 EXT_CSD_ERASE_GROUP_DEF, 1,
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 9a7d42c..2391990 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -990,9 +990,22 @@
 	return esdhc_change_pinstate(host, uhs);
 }
 
-static unsigned int esdhc_get_max_timeout_counter(struct sdhci_host *host)
+static unsigned int esdhc_get_max_timeout_count(struct sdhci_host *host)
 {
-	return 1 << 28;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+
+	return esdhc_is_usdhc(imx_data) ? 1 << 28 : 1 << 27;
+}
+
+static void esdhc_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+
+	/* use maximum timeout counter */
+	sdhci_writeb(host, esdhc_is_usdhc(imx_data) ? 0xF : 0xE,
+			SDHCI_TIMEOUT_CONTROL);
 }
 
 static struct sdhci_ops sdhci_esdhc_ops = {
@@ -1004,8 +1017,10 @@
 	.set_clock = esdhc_pltfm_set_clock,
 	.get_max_clock = esdhc_pltfm_get_max_clock,
 	.get_min_clock = esdhc_pltfm_get_min_clock,
+	.get_max_timeout_count = esdhc_get_max_timeout_count,
 	.get_ro = esdhc_pltfm_get_ro,
 	.platform_bus_width = esdhc_pltfm_bus_width,
+	.set_timeout = esdhc_set_timeout,
 	.set_uhs_signaling = esdhc_set_uhs_signaling,
 };
 
@@ -1170,9 +1185,7 @@
 		writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
 			| ESDHC_BURST_LEN_EN_INCR,
 			host->ioaddr + SDHCI_HOST_CONTROL);
-
-		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
-					SDHCI_QUIRK2_NOSTD_TIMEOUT_COUNTER;
+		host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
 		host->mmc->caps |= MMC_CAP_1_8V_DDR;
 
 		/*
@@ -1180,8 +1193,6 @@
 		 * TO1.1, it's harmless for MX6SL
 		 */
 		writel(readl(host->ioaddr + 0x6c) | BIT(7), host->ioaddr + 0x6c);
-		sdhci_esdhc_ops.get_max_timeout_counter =
-					esdhc_get_max_timeout_counter;
 	}
 
 	if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 7a87928..0af1637 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -717,19 +717,28 @@
 		sdhci_clear_set_irqs(host, dma_irqs, pio_irqs);
 }
 
-static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
+static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 {
 	u8 count;
+
+	if (host->ops->set_timeout) {
+		host->ops->set_timeout(host, cmd);
+	} else {
+		count = sdhci_calc_timeout(host, cmd);
+		sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
+	}
+}
+
+static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
+{
 	u8 ctrl;
 	struct mmc_data *data = cmd->data;
 	int ret;
 
 	WARN_ON(host->data);
 
-	if (data || (cmd->flags & MMC_RSP_BUSY)) {
-		count = sdhci_calc_timeout(host, cmd);
-		sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
-	}
+	if (data || (cmd->flags & MMC_RSP_BUSY))
+		sdhci_set_timeout(host, cmd);
 
 	if (!data)
 		return;
@@ -1218,7 +1227,6 @@
 clock_set:
 	if (real_div)
 		host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div;
-
 	clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
 	clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
 		<< SDHCI_DIVIDER_HI_SHIFT;
@@ -1453,6 +1461,18 @@
 
 	sdhci_set_clock(host, ios->clock);
 
+	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK &&
+	    host->clock) {
+		host->timeout_clk = host->mmc->actual_clock ?
+					host->mmc->actual_clock / 1000 :
+					host->clock / 1000;
+		host->mmc->max_busy_timeout =
+			host->ops->get_max_timeout_count ?
+			host->ops->get_max_timeout_count(host) :
+			1 << 27;
+		host->mmc->max_busy_timeout /= host->timeout_clk;
+	}
+
 	if (ios->power_mode == MMC_POWER_OFF)
 		vdd_bit = sdhci_set_power(host, -1);
 	else
@@ -3026,36 +3046,26 @@
 	} else
 		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
 
-	host->timeout_clk =
-		(caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
-	if (host->timeout_clk == 0) {
-		if (host->ops->get_timeout_clock) {
-			host->timeout_clk = host->ops->get_timeout_clock(host);
-		} else if (!(host->quirks &
-				SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
-			pr_err("%s: Hardware doesn't specify timeout clock "
-			       "frequency.\n", mmc_hostname(mmc));
-			return -ENODEV;
+	if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
+		host->timeout_clk = (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >>
+					SDHCI_TIMEOUT_CLK_SHIFT;
+		if (host->timeout_clk == 0) {
+			if (host->ops->get_timeout_clock) {
+				host->timeout_clk =
+					host->ops->get_timeout_clock(host);
+			} else {
+				pr_err("%s: Hardware doesn't specify timeout clock frequency.\n",
+					mmc_hostname(mmc));
+				return -ENODEV;
+			}
 		}
-	}
-	if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT)
-		host->timeout_clk *= 1000;
 
-	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
-		host->timeout_clk = mmc->f_max / 1000;
+		if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT)
+			host->timeout_clk *= 1000;
 
-	if (host->quirks2 & SDHCI_QUIRK2_NOSTD_TIMEOUT_COUNTER) {
-		if (host->ops->get_max_timeout_counter) {
-			mmc->max_discard_to =
-				host->ops->get_max_timeout_counter(host)
-					/ host->timeout_clk;
-		} else {
-			pr_err("%s: Hardware doesn't specify max timeout "
-				"counter\n", mmc_hostname(mmc));
-			return -ENODEV;
-		}
-	} else {
-		mmc->max_discard_to = (1 << 27) / host->timeout_clk;
+		mmc->max_busy_timeout = host->ops->get_max_timeout_count ?
+			host->ops->get_max_timeout_count(host) : 1 << 27;
+		mmc->max_busy_timeout /= host->timeout_clk;
 	}
 
 	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 4d38c29..8c58ba5 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -290,7 +290,9 @@
 	unsigned int	(*get_max_clock)(struct sdhci_host *host);
 	unsigned int	(*get_min_clock)(struct sdhci_host *host);
 	unsigned int	(*get_timeout_clock)(struct sdhci_host *host);
-	unsigned int	(*get_max_timeout_counter)(struct sdhci_host *host);
+	unsigned int	(*get_max_timeout_count)(struct sdhci_host *host);
+	void		(*set_timeout)(struct sdhci_host *host,
+				       struct mmc_command *cmd);
 	int		(*platform_bus_width)(struct sdhci_host *host,
 					       int width);
 	void (*platform_send_init_74_clocks)(struct sdhci_host *host,
diff --git a/drivers/mxc/sim/imx_sim.c b/drivers/mxc/sim/imx_sim.c
index 318f9d7..3687242 100755
--- a/drivers/mxc/sim/imx_sim.c
+++ b/drivers/mxc/sim/imx_sim.c
@@ -926,69 +926,36 @@
 	__raw_writel(reg_data, sim->ioaddr + sim->port_detect_reg);
 };
 
-static void sim_activate(struct sim_t *sim)
-{
-	u32 reg_data;
-	pr_debug("%s Activate on the sim port.\n", __func__);
-	/* activate on sequence */
-	if (sim->present != SIM_PRESENT_REMOVED) {
-		/*Disable Reset pin*/
-		reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
-		reg_data &= ~SIM_PORT_CNTL_SRST;
-		/*If sven is low active, we need to set sevn to be high*/
-		if (sim->sven_low_active)
-			reg_data |= SIM_PORT_CNTL_SVEN;
-
-		__raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
-
-		/*Enable VCC pin*/
-		reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
-
-		if (sim->sven_low_active)
-			reg_data &= ~SIM_PORT_CNTL_SVEN;
-		else
-			reg_data |= SIM_PORT_CNTL_SVEN;
-
-		__raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
-
-		msleep(10);
-		/*Enable clock pin*/
-		reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
-		reg_data |= SIM_PORT_CNTL_SCEN;
-		__raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
-		msleep(10);
-	} else {
-		pr_err("No card%s\n", __func__);
-	}
-}
-
 static void sim_cold_reset_sequency(struct sim_t *sim)
 {
 	u32 reg_data;
 
 	sim->state = SIM_STATE_RESET_SEQUENCY;
-	reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
-	reg_data &= ~SIM_PORT_CNTL_SRST;
-	__raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
-	reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
 
+	/*set VCC*/
+	reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
 	if (sim->sven_low_active)
 		reg_data &= ~SIM_PORT_CNTL_SVEN;
 	else
 		reg_data |= SIM_PORT_CNTL_SVEN;
-
 	__raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
+
 	msleep(9);
 
+	/*enable CLK*/
 	reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
 	reg_data |= SIM_PORT_CNTL_SCEN;
 	__raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
 
+	/*RST low time*/
 	sim_reset_low_timing(sim, EMV_RESET_LOW_CYCLES);
 
+	/*RST high*/
 	reg_data = __raw_readl(sim->ioaddr + sim->port_ctrl_reg);
 	reg_data |= SIM_PORT_CNTL_SRST;
 	__raw_writel(reg_data, sim->ioaddr + sim->port_ctrl_reg);
+
+	/*wait for ATR*/
 	sim_set_gpc_timer(sim, ATR_MAX_DELAY_CLK);
 };
 
@@ -1406,7 +1373,6 @@
 		sim_reset_module(sim);
 		sim_data_reset(sim);
 		sim_start(sim);
-		sim_activate(sim);
 		sim_cold_reset(sim);
 
 		break;
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index c7f587c..4b628e9 100644
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -24,6 +24,10 @@
  * $Id: dhd_sdio.c 506047 2014-10-02 12:43:31Z $
  */
 
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+
 #include <typedefs.h>
 #include <osl.h>
 #include <bcmsdh.h>
@@ -53,6 +57,7 @@
 #include <sbsdpcmdev.h>
 #include <bcmsdpcm.h>
 #include <bcmsdbus.h>
+#include <bcmsdh_sdmmc.h>
 
 #include <proto/ethernet.h>
 #include <proto/802.1d.h>
@@ -1737,6 +1742,9 @@
 	uint32 swhdr_offset;
 	bool alloc_new_pkt = FALSE;
 	uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
+	sdioh_info_t *sd = bus->sdh->sdioh;
+	struct sdio_func *sdio_func = sd->func[0];
+	struct mmc_host *host = sdio_func->card->host;
 
 	*new_pkt = NULL;
 	osh = bus->dhd->osh;
@@ -1814,7 +1822,7 @@
 			 * Use the padding packet to avoid memory copy if applicable,
 			 * otherwise, just allocate a new pkt.
 			 */
-			if (bus->pad_pkt) {
+			if (bus->pad_pkt && (host->max_segs > 1)) {
 				*pad_pkt_len = chain_tail_padding;
 				bus->tx_tailpad_chain++;
 			} else {
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 90c653d..405c184 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -1412,11 +1412,7 @@
 		 * reserved ddr memory after write the ddr_test_region
 		 * content to rc.
 		 */
-		if (is_imx7d_pcie(imx6_pcie))
-			pcie_arb_base_addr = ioremap_nocache(pp->mem_base,
-					test_region_size);
-		else
-			pcie_arb_base_addr = ioremap_cache(pp->mem_base,
+		pcie_arb_base_addr = ioremap_nocache(pp->mem_base,
 					test_region_size);
 
 		if (!pcie_arb_base_addr) {
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 67b1526..78b4a8e 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -246,7 +246,6 @@
 	unsigned int		tx_bytes;
 	unsigned int		dma_tx_nents;
 	struct delayed_work	tsk_dma_tx;
-	struct work_struct	tsk_dma_rx;
 	wait_queue_head_t	dma_wait;
 	unsigned int            saved_reg[10];
 #define DMA_TX_IS_WORKING 1
@@ -896,7 +895,6 @@
 }
 
 #define RX_BUF_SIZE	(PAGE_SIZE)
-static int start_rx_dma(struct imx_port *sport);
 
 static void dma_rx_push_data(struct imx_port *sport, struct tty_struct *tty,
 				unsigned int start, unsigned int end)
@@ -917,9 +915,8 @@
 	}
 }
 
-static void dma_rx_work(struct work_struct *w)
+static void dma_rx_work(struct imx_port *sport)
 {
-	struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_rx);
 	struct tty_struct *tty = sport->port.state->port.tty;
 	unsigned int cur_idx = sport->rx_buf.cur_idx;
 
@@ -970,14 +967,6 @@
 
 	status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
 	count = RX_BUF_SIZE - state.residue;
-
-	if (readl(sport->port.membase + USR2) & USR2_IDLE) {
-		/* In condition [3] the SDMA counted up too early */
-		count--;
-
-		writel(USR2_IDLE, sport->port.membase + USR2);
-	}
-
 	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++;
@@ -988,7 +977,7 @@
 		dev_err(sport->port.dev, "overwrite!\n");
 
 	if (count)
-		schedule_work(&sport->tsk_dma_rx);
+		dma_rx_work(sport);
 }
 
 static int start_rx_dma(struct imx_port *sport)
@@ -1227,10 +1216,8 @@
 		&& !sport->dma_is_inited)
 		imx_uart_dma_init(sport);
 
-	if (sport->dma_is_inited) {
+	if (sport->dma_is_inited)
 		INIT_DELAYED_WORK(&sport->tsk_dma_tx, dma_tx_work);
-		INIT_WORK(&sport->tsk_dma_rx, dma_rx_work);
-	}
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 	/*
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 3fa83db..db3b830 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -664,6 +664,15 @@
 	if (host->cur_blank != FB_BLANK_UNBLANK)
 		return 0;
 
+	line_size =  fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
+	fb_info->fix.line_length = line_size;
+	fb_size = fb_info->var.yres_virtual * line_size;
+
+	if (fb_size > fb_info->fix.smem_len) {
+		dev_err(&host->pdev->dev, "exceeds the fb buffer size limit!\n");
+		return -ENOMEM;
+	}
+
 	/*
 	 * It seems, you can't re-program the controller if it is still running.
 	 * This may lead into shifted pictures (FIFO issue?).
@@ -677,19 +686,6 @@
 	/* clear the FIFOs */
 	writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
 
-	line_size =  fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
-	fb_info->fix.line_length = line_size;
-	fb_size = fb_info->var.yres_virtual * line_size;
-
-	/* Reallocate memory */
-	if (!fb_info->fix.smem_start || (fb_size > fb_info->fix.smem_len)) {
-		if (fb_info->fix.smem_start)
-			mxsfb_unmap_videomem(fb_info);
-
-		if (mxsfb_map_videomem(fb_info) < 0)
-			return -ENOMEM;
-	}
-
 	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER |
 		CTRL_SET_BUS_WIDTH(host->ld_intf_width);
 
@@ -1259,6 +1255,7 @@
 
 	fb_info->fix.line_length =
 		fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
+	fb_info->fix.smem_len = SZ_32M;
 
 	/* Memory allocation for framebuffer */
 	if (mxsfb_map_videomem(fb_info) < 0)
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 84e005e7..b7a90c4 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -75,7 +75,7 @@
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
 	unsigned int		sec_erase_mult;	/* Secure erase multiplier */
 	unsigned int		trim_timeout;		/* In milliseconds */
-	bool			enhanced_area_en;	/* enable bit */
+	bool			partition_setting_completed;	/* enable bit */
 	unsigned long long	enhanced_area_offset;	/* Units: Byte */
 	unsigned int		enhanced_area_size;	/* Units: KB */
 	unsigned int		cache_size;		/* Units: KB */
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index d35e58b..48953c7 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -315,7 +315,7 @@
 	unsigned int		max_req_size;	/* maximum number of bytes in one req */
 	unsigned int		max_blk_size;	/* maximum size of one mmc block */
 	unsigned int		max_blk_count;	/* maximum number of blocks in one req */
-	unsigned int		max_discard_to;	/* max. discard timeout in ms */
+	unsigned int		max_busy_timeout; /* max busy timeout in ms */
 
 	/* private data */
 	spinlock_t		lock;		/* lock for claim and bus ops */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 0532437..9776b2a 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -281,6 +281,7 @@
 #define EXT_CSD_EXP_EVENTS_CTRL		56	/* R/W, 2 bytes */
 #define EXT_CSD_DATA_SECTOR_SIZE	61	/* R */
 #define EXT_CSD_GP_SIZE_MULT		143	/* R/W */
+#define EXT_CSD_PARTITION_SETTING_COMPLETED 155	/* R/W */
 #define EXT_CSD_PARTITION_ATTRIBUTE	156	/* R/W */
 #define EXT_CSD_PARTITION_SUPPORT	160	/* RO */
 #define EXT_CSD_HPI_MGMT		161	/* R/W */
@@ -351,6 +352,7 @@
 #define EXT_CSD_PART_CONFIG_ACC_RPMB	(0x3)
 #define EXT_CSD_PART_CONFIG_ACC_GP0	(0x4)
 
+#define EXT_CSD_PART_SETTING_COMPLETED	(0x1)
 #define EXT_CSD_PART_SUPPORT_PART_EN	(0x1)
 
 #define EXT_CSD_CMD_SET_NORMAL		(1<<0)
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 0fdff06..714ae21 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -101,7 +101,6 @@
 #define SDHCI_QUIRK2_NO_1_8_V				(1<<2)
 #define SDHCI_QUIRK2_PRESET_VALUE_BROKEN		(1<<3)
 #define SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON		(1<<4)
-#define SDHCI_QUIRK2_NOSTD_TIMEOUT_COUNTER		(1<<5)
 /* Controller has a non-standard host control register */
 #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL		(1<<5)
 /* Controller does not support HS200 */
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 13412ab..5f2ce73 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -625,7 +625,8 @@
 	enum snd_soc_bias_level suspend_bias_level;
 	struct delayed_work delayed_work;
 	unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
-
+	/* Go to BIAS_OFF in suspend if the DAPM context is idle */
+	unsigned int suspend_bias_off:1;
 	void (*seq_notifier)(struct snd_soc_dapm_context *,
 			     enum snd_soc_dapm_type, int);
 
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 59a4785..91a9efd 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -774,6 +774,7 @@
 	int (*set_bias_level)(struct snd_soc_codec *,
 			      enum snd_soc_bias_level level);
 	bool idle_bias_off;
+	bool suspend_bias_off;
 
 	void (*seq_notifier)(struct snd_soc_dapm_context *,
 			     enum snd_soc_dapm_type, int);
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 8715361..50079fa 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -1122,7 +1122,7 @@
 static struct snd_soc_codec_driver soc_codec_dev_wm8960 = {
 	.probe =	wm8960_probe,
 	.set_bias_level = wm8960_set_bias_level,
-	.idle_bias_off = true,
+	.suspend_bias_off = true,
 };
 
 static const struct regmap_config wm8960_regmap = {
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 8f5fe19..21667fd 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -1782,8 +1782,11 @@
 
 SOC_DOUBLE("ALC Switch", WM8962_ALC1, WM8962_ALCL_ENA_SHIFT,
 		WM8962_ALCR_ENA_SHIFT, 1, 0),
-SND_SOC_BYTES_MASK("ALC Coefficients", WM8962_ALC1, 4,
+SND_SOC_BYTES_MASK("ALC1", WM8962_ALC1, 1,
 		WM8962_ALCL_ENA_MASK | WM8962_ALCR_ENA_MASK),
+SND_SOC_BYTES("ALC2", WM8962_ALC2, 1),
+SND_SOC_BYTES("ALC3", WM8962_ALC3, 1),
+SND_SOC_BYTES("Noise Gate", WM8962_NOISE_GATE, 1),
 };
 
 static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 56a21e7..e00ce58 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -4375,6 +4375,7 @@
 	codec->dapm.codec = codec;
 	codec->dapm.seq_notifier = codec_drv->seq_notifier;
 	codec->dapm.stream_event = codec_drv->stream_event;
+	codec->dapm.suspend_bias_off = codec_drv->suspend_bias_off;
 	codec->dev = dev;
 	codec->driver = codec_drv;
 	codec->num_dai = num_dai;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index f504fae..331a440 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1807,6 +1807,22 @@
 	}
 }
 
+static bool dapm_idle_bias_off(struct snd_soc_dapm_context *dapm)
+{
+	if (dapm->idle_bias_off)
+		return true;
+
+	switch (snd_power_get_state(dapm->card->snd_card)) {
+	case SNDRV_CTL_POWER_D3hot:
+	case SNDRV_CTL_POWER_D3cold:
+		return dapm->suspend_bias_off;
+	default:
+		break;
+	}
+
+	return false;
+}
+
 /*
  * Scan each dapm widget for complete audio path.
  * A complete path is a route that has valid endpoints i.e.:-
@@ -1828,7 +1844,7 @@
 	trace_snd_soc_dapm_start(card);
 
 	list_for_each_entry(d, &card->dapm_list, list) {
-		if (d->idle_bias_off)
+		if (dapm_idle_bias_off(d))
 			d->target_bias_level = SND_SOC_BIAS_OFF;
 		else
 			d->target_bias_level = SND_SOC_BIAS_STANDBY;
@@ -1894,7 +1910,7 @@
 		if (d->target_bias_level > bias)
 			bias = d->target_bias_level;
 	list_for_each_entry(d, &card->dapm_list, list)
-		if (!d->idle_bias_off)
+		if (!dapm_idle_bias_off(d))
 			d->target_bias_level = bias;
 
 	trace_snd_soc_dapm_walk_done(card);